You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tamaya.apache.org by pl...@apache.org on 2015/12/20 14:05:55 UTC
[8/8] incubator-tamaya git commit: Moved module core to ./code/
Moved module core to ./code/
Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/commit/eadbfe97
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/tree/eadbfe97
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/diff/eadbfe97
Branch: refs/heads/master
Commit: eadbfe97395bded760b9492297f31b6421ce2a0f
Parents: 84d52f1
Author: Oliver B. Fischer <pl...@apache.org>
Authored: Sun Dec 20 14:05:42 2015 +0100
Committer: Oliver B. Fischer <pl...@apache.org>
Committed: Sun Dec 20 14:05:42 2015 +0100
----------------------------------------------------------------------
code/core/pom.xml | 103 +++++
.../core/internal/DefaultConfiguration.java | 197 ++++++++
.../internal/DefaultConfigurationContext.java | 278 ++++++++++++
.../DefaultConfigurationContextBuilder.java | 153 +++++++
.../internal/DefaultConfigurationProvider.java | 68 +++
.../core/internal/DefaultServiceContext.java | 156 +++++++
.../tamaya/core/internal/OSGIActivator.java | 53 +++
.../core/internal/OSGIServiceComparator.java | 69 +++
.../core/internal/OSGIServiceContext.java | 83 ++++
.../tamaya/core/internal/OSGIServiceLoader.java | 158 +++++++
.../internal/PriorityServiceComparator.java | 67 +++
.../core/internal/PropertyConverterManager.java | 448 +++++++++++++++++++
.../core/internal/PropertyFilterComparator.java | 60 +++
.../tamaya/core/internal/PropertyFiltering.java | 131 ++++++
.../core/internal/PropertySourceComparator.java | 54 +++
.../tamaya/core/internal/ReflectionUtil.java | 42 ++
.../converters/BigDecimalConverter.java | 63 +++
.../converters/BigIntegerConverter.java | 94 ++++
.../internal/converters/BooleanConverter.java | 57 +++
.../core/internal/converters/ByteConverter.java | 71 +++
.../core/internal/converters/CharConverter.java | 69 +++
.../internal/converters/ClassConverter.java | 63 +++
.../internal/converters/CurrencyConverter.java | 89 ++++
.../internal/converters/DoubleConverter.java | 81 ++++
.../core/internal/converters/EnumConverter.java | 68 +++
.../internal/converters/FloatConverter.java | 81 ++++
.../internal/converters/IntegerConverter.java | 74 +++
.../core/internal/converters/LongConverter.java | 72 +++
.../internal/converters/NumberConverter.java | 72 +++
.../internal/converters/ShortConverter.java | 72 +++
.../core/internal/converters/URIConverter.java | 47 ++
.../core/internal/converters/URLConverter.java | 47 ++
.../core/propertysource/BasePropertySource.java | 85 ++++
.../EnvironmentPropertySource.java | 64 +++
.../propertysource/SimplePropertySource.java | 128 ++++++
.../propertysource/SystemPropertySource.java | 93 ++++
.../provider/JavaConfigurationProvider.java | 61 +++
.../services/org.apache.tamaya.Configuration | 19 +
...pache.tamaya.spi.ConfigurationContextBuilder | 19 +
...g.apache.tamaya.spi.ConfigurationProviderSpi | 19 +
.../org.apache.tamaya.spi.PropertyConverter | 33 ++
.../org.apache.tamaya.spi.PropertySource | 20 +
...org.apache.tamaya.spi.PropertySourceProvider | 19 +
.../org.apache.tamaya.spi.ServiceContext | 19 +
.../apache/tamaya/core/ConfigurationTest.java | 67 +++
.../java/org/apache/tamaya/core/internal/A.java | 29 ++
.../java/org/apache/tamaya/core/internal/B.java | 29 ++
.../java/org/apache/tamaya/core/internal/C.java | 56 +++
.../tamaya/core/internal/CTestConverter.java | 32 ++
.../internal/DefaultServiceContextTest.java | 140 ++++++
.../internal/PropertyConverterManagerTest.java | 179 ++++++++
.../converters/BigDecimalConverterTest.java | 103 +++++
.../converters/BooleanConverterTest.java | 108 +++++
.../internal/converters/ByteConverterTest.java | 81 ++++
.../internal/converters/CharConverterTest.java | 86 ++++
.../ConverterTestsPropertySource.java | 252 +++++++++++
.../converters/CurrencyConverterTest.java | 154 +++++++
.../converters/DoubleConverterTest.java | 175 ++++++++
.../internal/converters/EnumConverterTest.java | 60 +++
.../internal/converters/FloatConverterTest.java | 176 ++++++++
.../converters/IntegerConverterTest.java | 111 +++++
.../internal/converters/LongConverterTest.java | 111 +++++
.../converters/NumberConverterTest.java | 103 +++++
.../internal/converters/ShortConverterTest.java | 111 +++++
.../propertysource/BasePropertySourceTest.java | 104 +++++
.../EnvironmentPropertySourceTest.java | 62 +++
.../PropertiesFilePropertySourceTest.java | 58 +++
.../SystemPropertySourceTest.java | 99 ++++
.../provider/JavaConfigurationProviderTest.java | 60 +++
.../testdata/TestPropertyDefaultSource.java | 56 +++
.../core/testdata/TestPropertyFilter.java | 37 ++
.../testdata/TestPropertySourceProvider.java | 78 ++++
.../testdata/TestRemovingPropertyFilter.java | 41 ++
.../META-INF/javaconfiguration.properties | 22 +
...tServiceContextTest$InvalidPriorityInterface | 18 +
...efaultServiceContextTest$MultiImplsInterface | 20 +
.../org.apache.tamaya.spi.PropertyConverter | 19 +
.../org.apache.tamaya.spi.PropertyFilter | 20 +
.../org.apache.tamaya.spi.PropertySource | 22 +
...org.apache.tamaya.spi.PropertySourceProvider | 20 +
.../test/resources/overrideOrdinal.properties | 25 ++
.../core/src/test/resources/testfile.properties | 22 +
code/core/src/test/resources/x34.properties | 19 +
code/pom.xml | 1 +
core/pom.xml | 103 -----
.../core/internal/DefaultConfiguration.java | 197 --------
.../internal/DefaultConfigurationContext.java | 278 ------------
.../DefaultConfigurationContextBuilder.java | 153 -------
.../internal/DefaultConfigurationProvider.java | 68 ---
.../core/internal/DefaultServiceContext.java | 156 -------
.../tamaya/core/internal/OSGIActivator.java | 53 ---
.../core/internal/OSGIServiceComparator.java | 69 ---
.../core/internal/OSGIServiceContext.java | 83 ----
.../tamaya/core/internal/OSGIServiceLoader.java | 158 -------
.../internal/PriorityServiceComparator.java | 67 ---
.../core/internal/PropertyConverterManager.java | 448 -------------------
.../core/internal/PropertyFilterComparator.java | 60 ---
.../tamaya/core/internal/PropertyFiltering.java | 131 ------
.../core/internal/PropertySourceComparator.java | 54 ---
.../tamaya/core/internal/ReflectionUtil.java | 42 --
.../converters/BigDecimalConverter.java | 63 ---
.../converters/BigIntegerConverter.java | 94 ----
.../internal/converters/BooleanConverter.java | 57 ---
.../core/internal/converters/ByteConverter.java | 71 ---
.../core/internal/converters/CharConverter.java | 69 ---
.../internal/converters/ClassConverter.java | 63 ---
.../internal/converters/CurrencyConverter.java | 89 ----
.../internal/converters/DoubleConverter.java | 81 ----
.../core/internal/converters/EnumConverter.java | 68 ---
.../internal/converters/FloatConverter.java | 81 ----
.../internal/converters/IntegerConverter.java | 74 ---
.../core/internal/converters/LongConverter.java | 72 ---
.../internal/converters/NumberConverter.java | 72 ---
.../internal/converters/ShortConverter.java | 72 ---
.../core/internal/converters/URIConverter.java | 47 --
.../core/internal/converters/URLConverter.java | 47 --
.../core/propertysource/BasePropertySource.java | 85 ----
.../EnvironmentPropertySource.java | 64 ---
.../propertysource/SimplePropertySource.java | 128 ------
.../propertysource/SystemPropertySource.java | 93 ----
.../provider/JavaConfigurationProvider.java | 61 ---
.../services/org.apache.tamaya.Configuration | 19 -
...pache.tamaya.spi.ConfigurationContextBuilder | 19 -
...g.apache.tamaya.spi.ConfigurationProviderSpi | 19 -
.../org.apache.tamaya.spi.PropertyConverter | 33 --
.../org.apache.tamaya.spi.PropertySource | 20 -
...org.apache.tamaya.spi.PropertySourceProvider | 19 -
.../org.apache.tamaya.spi.ServiceContext | 19 -
.../apache/tamaya/core/ConfigurationTest.java | 67 ---
.../java/org/apache/tamaya/core/internal/A.java | 29 --
.../java/org/apache/tamaya/core/internal/B.java | 29 --
.../java/org/apache/tamaya/core/internal/C.java | 56 ---
.../tamaya/core/internal/CTestConverter.java | 32 --
.../internal/DefaultServiceContextTest.java | 140 ------
.../internal/PropertyConverterManagerTest.java | 179 --------
.../converters/BigDecimalConverterTest.java | 103 -----
.../converters/BooleanConverterTest.java | 108 -----
.../internal/converters/ByteConverterTest.java | 81 ----
.../internal/converters/CharConverterTest.java | 86 ----
.../ConverterTestsPropertySource.java | 252 -----------
.../converters/CurrencyConverterTest.java | 154 -------
.../converters/DoubleConverterTest.java | 175 --------
.../internal/converters/EnumConverterTest.java | 60 ---
.../internal/converters/FloatConverterTest.java | 176 --------
.../converters/IntegerConverterTest.java | 111 -----
.../internal/converters/LongConverterTest.java | 111 -----
.../converters/NumberConverterTest.java | 103 -----
.../internal/converters/ShortConverterTest.java | 111 -----
.../propertysource/BasePropertySourceTest.java | 104 -----
.../EnvironmentPropertySourceTest.java | 62 ---
.../PropertiesFilePropertySourceTest.java | 58 ---
.../SystemPropertySourceTest.java | 99 ----
.../provider/JavaConfigurationProviderTest.java | 60 ---
.../testdata/TestPropertyDefaultSource.java | 56 ---
.../core/testdata/TestPropertyFilter.java | 37 --
.../testdata/TestPropertySourceProvider.java | 78 ----
.../testdata/TestRemovingPropertyFilter.java | 41 --
.../META-INF/javaconfiguration.properties | 22 -
...tServiceContextTest$InvalidPriorityInterface | 18 -
...efaultServiceContextTest$MultiImplsInterface | 20 -
.../org.apache.tamaya.spi.PropertyConverter | 19 -
.../org.apache.tamaya.spi.PropertyFilter | 20 -
.../org.apache.tamaya.spi.PropertySource | 22 -
...org.apache.tamaya.spi.PropertySourceProvider | 20 -
.../test/resources/overrideOrdinal.properties | 25 --
core/src/test/resources/testfile.properties | 22 -
core/src/test/resources/x34.properties | 19 -
pom.xml | 1 -
168 files changed, 6785 insertions(+), 6785 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/eadbfe97/code/core/pom.xml
----------------------------------------------------------------------
diff --git a/code/core/pom.xml b/code/core/pom.xml
new file mode 100644
index 0000000..3088bd6
--- /dev/null
+++ b/code/core/pom.xml
@@ -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 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>code</artifactId>
+ <version>0.2-incubating-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>tamaya-core</artifactId>
+ <name>Apache Tamaya Core Implementation</name>
+ <packaging>bundle</packaging>
+
+ <properties>
+ <osgi.compendium.version>5.0.0</osgi.compendium.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tamaya</groupId>
+ <artifactId>tamaya-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-library</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ <scope>provided</scope>
+ <version>${osgi.compendium.version}</version>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <version>${osgi.version}</version>
+ <scope>provided</scope>
+ <optional>true</optional>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Import-Package>
+ org.apache.tamaya,
+ org.apache.tamaya.spi,
+ javax.annotation,
+ *
+ </Import-Package>
+ <Private-Package>
+ org.apache.tamaya.core.internal,
+ org.apache.tamaya.core.internal.converters
+ </Private-Package>
+ <Export-Package>
+ org.apache.tamaya.core,
+ org.apache.tamaya.core.propertysource,
+ org.apache.tamaya.core.provider
+ </Export-Package>
+ <Bundle-Activator>
+ org.apache.tamaya.core.internal.OSGIActivator
+ </Bundle-Activator>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/eadbfe97/code/core/src/main/java/org/apache/tamaya/core/internal/DefaultConfiguration.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/DefaultConfiguration.java b/code/core/src/main/java/org/apache/tamaya/core/internal/DefaultConfiguration.java
new file mode 100644
index 0000000..f7c363c
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/DefaultConfiguration.java
@@ -0,0 +1,197 @@
+/*
+ * 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.internal;
+
+import org.apache.tamaya.ConfigException;
+import org.apache.tamaya.ConfigOperator;
+import org.apache.tamaya.ConfigQuery;
+import org.apache.tamaya.Configuration;
+import org.apache.tamaya.TypeLiteral;
+import org.apache.tamaya.spi.*;
+
+import java.util.ArrayList;
+import java.util.Collections;
+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 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;
+
+
+ /**
+ * Constructor.
+ * @param configurationContext The configuration Context to be used.
+ */
+ public DefaultConfiguration(ConfigurationContext configurationContext){
+ this.configurationContext = Objects.requireNonNull(configurationContext);
+ }
+
+
+ public String get(String key) {
+ return PropertyFiltering.applyFilter(key, evaluteRawValue(key), configurationContext);
+ }
+
+ protected String evaluteRawValue(String key) {
+ List<PropertySource> propertySources = configurationContext.getPropertySources();
+ String unfilteredValue = null;
+ PropertyValueCombinationPolicy combinationPolicy = this.configurationContext
+ .getPropertyValueCombinationPolicy();
+ for (PropertySource propertySource : propertySources) {
+ unfilteredValue = combinationPolicy.collect(unfilteredValue, key, propertySource);
+ }
+ return unfilteredValue;
+ }
+
+
+ @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;
+ }
+
+ /**
+ * Get the current properties, composed by the loaded {@link PropertySource} and filtered
+ * by registered {@link PropertyFilter}.
+ *
+ * @return the final properties.
+ */
+ @Override
+ public Map<String, String> getProperties() {
+ return PropertyFiltering.applyFilters(evaluateUnfilteredMap(), configurationContext);
+ }
+
+ protected Map<String, String> evaluateUnfilteredMap() {
+ List<PropertySource> propertySources = new ArrayList<>(configurationContext.getPropertySources());
+ Collections.reverse(propertySources);
+ Map<String, String> result = new HashMap<>();
+ for (PropertySource propertySource : propertySources) {
+ try {
+ int origSize = result.size();
+ Map<String, String> otherMap = propertySource.getProperties();
+ LOG.log(Level.FINEST, null, "Overriding with properties from " + propertySource.getName());
+ result.putAll(otherMap);
+ LOG.log(Level.FINEST, null, "Handled properties from " + propertySource.getName() + "(new: " +
+ (result.size() - origSize) + ", overrides: " + origSize + ", total: " + result.size());
+ } catch (Exception e) {
+ LOG.log(Level.SEVERE, "Error adding properties from PropertySource: " + propertySource + ", ignoring PropertySource.", e);
+ }
+ }
+ 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}.
+ * @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, Class<T> type) {
+ return get(key, (TypeLiteral<T>)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) {
+ return convertValue(key, get(key), type);
+ }
+
+ 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, 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);
+ }
+ }
+ 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) {
+ 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);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/eadbfe97/code/core/src/main/java/org/apache/tamaya/core/internal/DefaultConfigurationContext.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/DefaultConfigurationContext.java b/code/core/src/main/java/org/apache/tamaya/core/internal/DefaultConfigurationContext.java
new file mode 100644
index 0000000..ac68a73
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/DefaultConfigurationContext.java
@@ -0,0 +1,278 @@
+/*
+ * 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.internal;
+
+import org.apache.tamaya.ConfigurationProvider;
+import org.apache.tamaya.TypeLiteral;
+import org.apache.tamaya.spi.ConfigurationContext;
+import org.apache.tamaya.spi.ConfigurationContextBuilder;
+import org.apache.tamaya.spi.PropertyConverter;
+import org.apache.tamaya.spi.PropertyFilter;
+import org.apache.tamaya.spi.PropertySource;
+import org.apache.tamaya.spi.PropertySourceProvider;
+import org.apache.tamaya.spi.PropertyValueCombinationPolicy;
+import org.apache.tamaya.spi.ServiceContextManager;
+
+import javax.annotation.Priority;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+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());
+ /**
+ * Cubcomponent handling {@link org.apache.tamaya.spi.PropertyConverter} instances.
+ */
+ private PropertyConverterManager propertyConverterManager = new PropertyConverterManager();
+
+ /**
+ * The current unmodifiable list of loaded {@link org.apache.tamaya.spi.PropertySource} instances.
+ */
+ private List<PropertySource> immutablePropertySources;
+
+ /**
+ * The current unmodifiable list of loaded {@link org.apache.tamaya.spi.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();
+
+ /** Comparator used for ordering property sources. */
+ private final PropertySourceComparator propertySourceComparator = new PropertySourceComparator();
+
+ /** Comparator used for ordering property filters. */
+ private final PropertyFilterComparator propertyFilterComparator = new PropertyFilterComparator();
+
+
+ /**
+ * The first time the Configuration system gets invoked we do initialize
+ * all our {@link org.apache.tamaya.spi.PropertySource}s and
+ * {@link org.apache.tamaya.spi.PropertyFilter}s which are known at startup.
+ */
+ public DefaultConfigurationContext() {
+ List<PropertySource> propertySources = new ArrayList<>();
+
+ // first we load all PropertySources which got registered via java.util.ServiceLoader
+ propertySources.addAll(ServiceContextManager.getServiceContext().getServices(PropertySource.class));
+
+ // after that we add all PropertySources which get dynamically registered via their PropertySourceProviders
+ propertySources.addAll(evaluatePropertySourcesFromProviders());
+
+ // now sort them according to their ordinal values
+ Collections.sort(propertySources, new PropertySourceComparator());
+
+ immutablePropertySources = Collections.unmodifiableList(propertySources);
+ LOG.info("Registered " + immutablePropertySources.size() + " property sources: " +
+ immutablePropertySources);
+
+ // as next step we pick up the PropertyFilters pretty much the same way
+ List<PropertyFilter> propertyFilters = new ArrayList<>();
+ propertyFilters.addAll(ServiceContextManager.getServiceContext().getServices(PropertyFilter.class));
+ Collections.sort(propertyFilters, new PropertyFilterComparator());
+ immutablePropertyFilters = Collections.unmodifiableList(propertyFilters);
+ LOG.info("Registered " + immutablePropertyFilters.size() + " property filters: " +
+ immutablePropertyFilters);
+
+ immutablePropertyFilters = Collections.unmodifiableList(propertyFilters);
+ LOG.info("Registered " + immutablePropertyFilters.size() + " property filters: " +
+ immutablePropertyFilters);
+ propertyValueCombinationPolicy = ServiceContextManager.getServiceContext().getService(PropertyValueCombinationPolicy.class);
+ if(propertyValueCombinationPolicy==null) {
+ propertyValueCombinationPolicy = PropertyValueCombinationPolicy.DEFAULT_OVERRIDING_COLLECTOR;
+ }
+ LOG.info("Using PropertyValueCombinationPolicy: " + propertyValueCombinationPolicy);
+ }
+
+ DefaultConfigurationContext(DefaultConfigurationContextBuilder builder) {
+ List<PropertySource> propertySources = new ArrayList<>();
+ // first we load all PropertySources which got registered via java.util.ServiceLoader
+ propertySources.addAll(builder.propertySources.values());
+ // now sort them according to their ordinal values
+ Collections.sort(propertySources, propertySourceComparator);
+ immutablePropertySources = Collections.unmodifiableList(propertySources);
+ LOG.info("Registered " + immutablePropertySources.size() + " property sources: " +
+ immutablePropertySources);
+
+ // as next step we pick up the PropertyFilters pretty much the same way
+ List<PropertyFilter> propertyFilters = new ArrayList<>();
+ propertyFilters.addAll(ServiceContextManager.getServiceContext().getServices(PropertyFilter.class));
+ Collections.sort(propertyFilters, propertyFilterComparator);
+ immutablePropertyFilters = Collections.unmodifiableList(propertyFilters);
+ LOG.info("Registered " + immutablePropertyFilters.size() + " property filters: " +
+ immutablePropertyFilters);
+
+ 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);
+ }
+
+ /**
+ * Pick up all {@link org.apache.tamaya.spi.PropertySourceProvider}s and return all the
+ * {@link org.apache.tamaya.spi.PropertySource}s they like to register.
+ */
+ private Collection<? extends PropertySource> evaluatePropertySourcesFromProviders() {
+ List<PropertySource> propertySources = new ArrayList<>();
+ Collection<PropertySourceProvider> propertySourceProviders = ServiceContextManager.getServiceContext().getServices(PropertySourceProvider.class);
+ for (PropertySourceProvider propertySourceProvider : propertySourceProviders) {
+ Collection<PropertySource> sources = propertySourceProvider.getPropertySources();
+ LOG.finer("PropertySourceProvider " + propertySourceProvider.getClass().getName() +
+ " provided the following property sources: " + sources);
+ propertySources.addAll(sources);
+ }
+
+ return propertySources;
+ }
+
+ @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, new PropertySourceComparator());
+
+ this.immutablePropertySources = Collections.unmodifiableList(newPropertySources);
+ } finally {
+ writeLock.unlock();
+ }
+ }
+
+ private static class PropertySourceComparator implements Comparator<PropertySource>, Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Order property source reversely, the most important come first.
+ *
+ * @param source1 the first PropertySource
+ * @param source2 the second PropertySource
+ * @return the comparison result.
+ */
+ private int comparePropertySources(PropertySource source1, PropertySource source2) {
+ if (source1.getOrdinal() < source2.getOrdinal()) {
+ return -1;
+ } else if (source1.getOrdinal() > source2.getOrdinal()) {
+ return 1;
+ } else {
+ return source1.getClass().getName().compareTo(source2.getClass().getName());
+ }
+ }
+
+ @Override
+ public int compare(PropertySource source1, PropertySource source2) {
+ return comparePropertySources(source1, source2);
+ }
+ }
+
+ private static class PropertyFilterComparator implements Comparator<PropertyFilter>, Serializable{
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 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);
+ }
+ }
+
+ @Override
+ public List<PropertySource> getPropertySources() {
+ return immutablePropertySources;
+ }
+
+ @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 ConfigurationProvider.getConfigurationContextBuilder().setContext(this);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/eadbfe97/code/core/src/main/java/org/apache/tamaya/core/internal/DefaultConfigurationContextBuilder.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/DefaultConfigurationContextBuilder.java b/code/core/src/main/java/org/apache/tamaya/core/internal/DefaultConfigurationContextBuilder.java
new file mode 100644
index 0000000..2c44689
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/DefaultConfigurationContextBuilder.java
@@ -0,0 +1,153 @@
+/*
+ * 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.internal;
+
+import org.apache.tamaya.ConfigException;
+import org.apache.tamaya.spi.PropertyConverter;
+import org.apache.tamaya.TypeLiteral;
+import org.apache.tamaya.spi.ConfigurationContext;
+import org.apache.tamaya.spi.ConfigurationContextBuilder;
+import org.apache.tamaya.spi.PropertyFilter;
+import org.apache.tamaya.spi.PropertySource;
+import org.apache.tamaya.spi.PropertyValueCombinationPolicy;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * Default implementation of {@link org.apache.tamaya.spi.ConfigurationContextBuilder}.
+ */
+public class DefaultConfigurationContextBuilder implements ConfigurationContextBuilder {
+
+ Map<String, PropertySource> propertySources = new HashMap<>();
+ List<PropertyFilter> propertyFilters = new ArrayList<>();
+ Map<TypeLiteral<?>, List<PropertyConverter<?>>> propertyConverters = new HashMap<>();
+ PropertyValueCombinationPolicy combinationPolicy;
+
+ public DefaultConfigurationContextBuilder(){
+ }
+
+ @Override
+ public ConfigurationContextBuilder setContext(ConfigurationContext context) {
+ this.propertySources.clear();
+ for(PropertySource ps:context.getPropertySources()) {
+ this.propertySources.put(ps.getName(), ps);
+ }
+ this.propertyFilters.clear();
+ this.propertyFilters.addAll(context.getPropertyFilters());
+ this.propertyConverters.clear();
+ this.propertyConverters.putAll(context.getPropertyConverters());
+ this.combinationPolicy = context.getPropertyValueCombinationPolicy();
+ return this;
+ }
+
+ @Override
+ public ConfigurationContextBuilder addPropertySources(Collection<PropertySource> propertySourcesToAdd) {
+ for(PropertySource ps:propertySourcesToAdd){
+ if(this.propertySources.containsKey(ps.getName())){
+ throw new ConfigException("Duplicate PropertySource: " + ps.getName());
+ }
+ }
+ for(PropertySource ps:propertySourcesToAdd) {
+ this.propertySources.put(ps.getName(), ps);
+ }
+ return this;
+ }
+
+ @Override
+ public ConfigurationContextBuilder addPropertySources(PropertySource... propertySourcesToAdd) {
+ return addPropertySources(Arrays.asList(propertySourcesToAdd));
+ }
+
+ @Override
+ public ConfigurationContextBuilder removePropertySources(Collection<String> propertySourcesToRemove) {
+ for(String key: propertySourcesToRemove){
+ this.propertySources.remove(key);
+ }
+ return this;
+ }
+
+ @Override
+ public ConfigurationContextBuilder removePropertySources(String... propertySourcesToRemove) {
+ return removePropertySources(Arrays.asList(propertySourcesToRemove));
+ }
+
+ @Override
+ public ConfigurationContextBuilder addPropertyFilters(Collection<PropertyFilter> filters) {
+ this.propertyFilters.addAll(filters);
+ return this;
+ }
+
+ @Override
+ public ConfigurationContextBuilder addPropertyFilters(PropertyFilter... filters) {
+ return addPropertyFilters(Arrays.asList(filters));
+ }
+
+ @Override
+ public ConfigurationContextBuilder removePropertyFilters(Collection<PropertyFilter> filters) {
+ this.propertyFilters.removeAll(filters);
+ return this;
+ }
+
+ @Override
+ public ConfigurationContextBuilder removePropertyFilters(PropertyFilter... filters) {
+ return removePropertyFilters(Arrays.asList(filters));
+ }
+
+ @Override
+ public <T> ConfigurationContextBuilder addPropertyConverter(TypeLiteral<T> typeToConvert, PropertyConverter<T> propertyConverter) {
+ List<PropertyConverter<?>> converters = this.propertyConverters.get(typeToConvert);
+ if(converters==null){
+ converters = new ArrayList<>();
+ this.propertyConverters.put(typeToConvert, converters);
+ }
+ return this;
+ }
+
+ @Override
+ public ConfigurationContextBuilder removePropertyConverters(TypeLiteral<?> typeToConvert, PropertyConverter<?>... converters) {
+ return removePropertyConverters(typeToConvert, Arrays.asList(converters));
+ }
+
+ @Override
+ public ConfigurationContextBuilder removePropertyConverters(TypeLiteral<?> typeToConvert, Collection<PropertyConverter<?>> converters) {
+ List<PropertyConverter<?>> existing = this.propertyConverters.get(typeToConvert);
+ if(existing!=null) {
+ existing.removeAll(converters);
+ }
+ return this;
+ }
+
+ @Override
+ public ConfigurationContextBuilder setPropertyValueCombinationPolicy(PropertyValueCombinationPolicy policy) {
+ this.combinationPolicy = Objects.requireNonNull(policy);
+ return this;
+ }
+
+ @Override
+ public ConfigurationContext build() {
+ return new DefaultConfigurationContext(this);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/eadbfe97/code/core/src/main/java/org/apache/tamaya/core/internal/DefaultConfigurationProvider.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/DefaultConfigurationProvider.java b/code/core/src/main/java/org/apache/tamaya/core/internal/DefaultConfigurationProvider.java
new file mode 100644
index 0000000..2dc15bd
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/DefaultConfigurationProvider.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.core.internal;
+
+import org.apache.tamaya.Configuration;
+import org.apache.tamaya.spi.ConfigurationContext;
+import org.apache.tamaya.spi.ConfigurationContextBuilder;
+import org.apache.tamaya.spi.ConfigurationProviderSpi;
+import org.apache.tamaya.spi.ServiceContextManager;
+
+/**
+ * Implementation of the Configuration API. This class uses the current {@link org.apache.tamaya.spi.ConfigurationContext} to evaluate the
+ * chain of {@link org.apache.tamaya.spi.PropertySource} and {@link org.apache.tamaya.spi.PropertyFilter}
+ * instance to evaluate the current Configuration.
+ */
+public class DefaultConfigurationProvider implements ConfigurationProviderSpi {
+
+ private ConfigurationContext context = new DefaultConfigurationContext();
+ private Configuration config = new DefaultConfiguration(context);
+
+ @Override
+ public Configuration getConfiguration() {
+ return config;
+ }
+
+ @Override
+ public ConfigurationContext getConfigurationContext() {
+ return context;
+ }
+
+ @Override
+ public ConfigurationContextBuilder getConfigurationContextBuilder() {
+ ConfigurationContextBuilder contextBuilder =
+ ServiceContextManager.getServiceContext().getService(ConfigurationContextBuilder.class);
+
+ return contextBuilder;
+ }
+
+ @Override
+ public void setConfigurationContext(ConfigurationContext context){
+ // TODO think on a SPI or move event part into API...
+ this.config = new DefaultConfiguration(context);
+ this.context = context;
+ }
+
+
+ @Override
+ public boolean isConfigurationContextSettable() {
+ return true;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/eadbfe97/code/core/src/main/java/org/apache/tamaya/core/internal/DefaultServiceContext.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/DefaultServiceContext.java b/code/core/src/main/java/org/apache/tamaya/core/internal/DefaultServiceContext.java
new file mode 100644
index 0000000..9738b76
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/DefaultServiceContext.java
@@ -0,0 +1,156 @@
+/*
+ * 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.internal;
+
+import org.apache.tamaya.ConfigException;
+import org.apache.tamaya.spi.ServiceContext;
+
+import javax.annotation.Priority;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.ServiceLoader;
+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 DefaultServiceContext implements ServiceContext {
+ /**
+ * List current services loaded, per class.
+ */
+ private final ConcurrentHashMap<Class<?>, List<Object>> servicesLoaded = new ConcurrentHashMap<>();
+ /**
+ * Singletons.
+ */
+ private final Map<Class<?>, Object> singletons = new ConcurrentHashMap<>();
+
+ @Override
+ public <T> T getService(Class<T> serviceType) {
+ Object cached = singletons.get(serviceType);
+ if (cached == null) {
+ Collection<T> services = getServices(serviceType);
+ if (services.isEmpty()) {
+ cached = null;
+ } else {
+ cached = getServiceWithHighestPriority(services, serviceType);
+ }
+ if(cached!=null) {
+ singletons.put(serviceType, cached);
+ }
+ }
+ return serviceType.cast(cached);
+ }
+
+ /**
+ * Loads and registers services.
+ *
+ * @param <T> the concrete type.
+ * @param serviceType The service type.
+ * @return the items found, never {@code null}.
+ */
+ @Override
+ public <T> List<T> getServices(final Class<T> serviceType) {
+ List<T> found = (List<T>) servicesLoaded.get(serviceType);
+ if (found != null) {
+ return found;
+ }
+ List<T> services = new ArrayList<>();
+ try {
+ for (T t : ServiceLoader.load(serviceType)) {
+ services.add(t);
+ }
+ services = Collections.unmodifiableList(services);
+ } catch (Exception e) {
+ Logger.getLogger(DefaultServiceContext.class.getName()).log(Level.WARNING,
+ "Error loading services current type " + serviceType, e);
+ }
+ final List<T> previousServices = List.class.cast(servicesLoaded.putIfAbsent(serviceType, (List<Object>) services));
+ return previousServices != null ? previousServices : services;
+ }
+
+ /**
+ * Checks the given instance for a @Priority annotation. If present the annotation's value s evaluated. If no such
+ * annotation is present, a default priority is returned (1);
+ * @param o the instance, not null.
+ * @return a priority, by default 1.
+ */
+ public static int getPriority(Object o){
+ int prio = 1; //X TODO discuss default priority
+ Priority priority = o.getClass().getAnnotation(Priority.class);
+ if (priority != null) {
+ prio = priority.value();
+ }
+ return prio;
+ }
+
+ /**
+ * @param services to scan
+ * @param <T> type of the service
+ *
+ * @return the service with the highest {@link javax.annotation.Priority#value()}
+ *
+ * @throws ConfigException if there are multiple service implementations with the maximum priority
+ */
+ private <T> T getServiceWithHighestPriority(Collection<T> services, Class<T> serviceType) {
+
+ // we do not need the priority stuff if the list contains only one element
+ if (services.size() == 1) {
+ return services.iterator().next();
+ }
+
+ Integer highestPriority = null;
+ int highestPriorityServiceCount = 0;
+ T highestService = null;
+
+ for (T service : services) {
+ int prio = getPriority(service);
+ if (highestPriority == null || highestPriority < prio) {
+ highestService = service;
+ highestPriorityServiceCount = 1;
+ highestPriority = prio;
+ } else if (highestPriority == prio) {
+ highestPriorityServiceCount++;
+ }
+ }
+
+ if (highestPriorityServiceCount > 1) {
+ throw new ConfigException(MessageFormat.format("Found {0} implementations for Service {1} with Priority {2}: {3}",
+ highestPriorityServiceCount,
+ serviceType.getName(),
+ highestPriority,
+ services));
+ }
+
+ return highestService;
+ }
+
+ @Override
+ public int ordinal() {
+ return 1;
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/eadbfe97/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIActivator.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIActivator.java b/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIActivator.java
new file mode 100644
index 0000000..8a54d35
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIActivator.java
@@ -0,0 +1,53 @@
+/*
+ * 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.internal;
+
+
+
+import org.apache.tamaya.spi.ServiceContextManager;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+import java.util.logging.Logger;
+
+/**
+ * A bundle activator that registers the {@link OSGIServiceLoader}.
+ */
+public class OSGIActivator implements BundleActivator {
+
+ private static final Logger LOG = Logger.getLogger(OSGIActivator.class.getName());
+
+ private OSGIServiceLoader serviceLoader;
+
+ @Override
+ public void start(BundleContext context) {
+ // Register marker service
+ ServiceContextManager.set(new OSGIServiceContext(context));
+ LOG.info("Registered OSGI enabled ServiceContext...");
+ serviceLoader = new OSGIServiceLoader();
+ context.addBundleListener(serviceLoader);
+ }
+
+ @Override
+ public void stop(BundleContext context) {
+ if(serviceLoader!=null) {
+ context.removeBundleListener(serviceLoader);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/eadbfe97/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceComparator.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceComparator.java b/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceComparator.java
new file mode 100644
index 0000000..bfc34bc
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceComparator.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.internal;
+
+import org.osgi.framework.ServiceReference;
+
+import javax.annotation.Priority;
+import java.util.Comparator;
+
+/**
+ * Comparator implementation for odering services loaded based on their increasing priority values.
+ */
+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 s evaluated. If no such
+ * annotation is present, a default priority is returned (1);
+ *
+ * @param o the instance, not 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 s evaluated.
+ * If no such annotation is present, a default priority is returned (1);
+ *
+ * @param type the type, not null.
+ * @return a priority, by default 1.
+ */
+ 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/eadbfe97/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceContext.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceContext.java b/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceContext.java
new file mode 100644
index 0000000..083cd54
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceContext.java
@@ -0,0 +1,83 @@
+/*
+ * 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.internal;
+
+import org.apache.tamaya.spi.ServiceContext;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * ServiceContext implementation based on OSGI Service mechanisms.
+ */
+public class OSGIServiceContext implements ServiceContext{
+
+ private static final OSGIServiceComparator REF_COMPARATOR = new OSGIServiceComparator();
+
+ private BundleContext bundleContext;
+
+ public OSGIServiceContext(BundleContext bundleContext){
+ this.bundleContext = Objects.requireNonNull(bundleContext);
+ }
+
+ public boolean isInitialized(){
+ return bundleContext != null;
+ }
+
+
+ @Override
+ public int ordinal() {
+ return 10;
+ }
+
+ @Override
+ public <T> T getService(Class<T> serviceType) {
+ ServiceReference<T> ref = this.bundleContext.getServiceReference(serviceType);
+ if(ref!=null){
+ return this.bundleContext.getService(ref);
+ }
+ return null;
+ }
+
+ @Override
+ public <T> List<T> getServices(Class<T> serviceType) {
+ List<ServiceReference<T>> refs = new ArrayList<>();
+ try {
+ refs.addAll(this.bundleContext.getServiceReferences(serviceType, null));
+ Collections.sort(refs, REF_COMPARATOR);
+ List<T> services = new ArrayList<>(refs.size());
+ for(ServiceReference<T> ref:refs){
+ T service = bundleContext.getService(ref);
+ if(service!=null) {
+ services.add(service);
+ }
+ }
+ return services;
+ } catch (InvalidSyntaxException e) {
+ e.printStackTrace();
+ return Collections.emptyList();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/eadbfe97/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceLoader.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceLoader.java b/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceLoader.java
new file mode 100644
index 0000000..dcc702f
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceLoader.java
@@ -0,0 +1,158 @@
+/*
+ * 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.internal;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.ConcurrentModificationException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleListener;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.util.tracker.ServiceTracker;
+
+/**
+ * An bundle listener that registers services defined in META-INF/services, when a bundle is starting.
+ *
+ * @author anatole@apache.org
+ */
+public class OSGIServiceLoader implements BundleListener {
+ // Provide logging
+ private static final Logger log = Logger.getLogger(OSGIServiceLoader.class.getName());
+
+ private Map<Class, ServiceTracker<Object,Object>> services = new ConcurrentHashMap<>();
+
+ @Override
+ public void bundleChanged(BundleEvent bundleEvent) {
+ // Parse and create metadta on STARTING
+ if (bundleEvent.getType() == BundleEvent.STARTED) {
+ Bundle bundle = bundleEvent.getBundle();
+ if (bundle.getEntry("META-INF/services/") == null) {
+ return;
+ }
+ 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());
+ 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) {
+ try {
+ // Load the service class
+ Class<?> implClass = (Class<?>) bundle.loadClass(implClassName);
+ if (serviceClass.isAssignableFrom(implClass) == false) {
+ log.warning("Configured service: " + implClassName + " is not assignble to " +
+ serviceClass.getName());
+ continue;
+ }
+ // Provide service properties
+ Hashtable<String, String> props = new Hashtable<String, String>();
+ props.put(Constants.VERSION_ATTRIBUTE, bundle.getVersion().toString());
+ String vendor = (String) 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);
+ }
+ catch(Exception e){
+ log.log(Level.SEVERE,
+ "Failed to load service class using ServiceLoader logic: " + implClassName, e);
+ }
+ }
+ 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 Class<?> serviceClass;
+
+ public JDKUtilServiceFactory(Class<?> serviceClass) {
+ this.serviceClass = serviceClass;
+ }
+
+ @Override
+ public Object getService(Bundle bundle, ServiceRegistration registration) {
+ try {
+ Object serviceInstance = serviceClass.newInstance();
+ return serviceInstance;
+ }
+ catch (Exception ex) {
+ ex.printStackTrace();
+ throw new IllegalStateException("Cannot instanciate service", ex);
+ }
+ }
+
+ @Override
+ public void ungetService(Bundle bundle, ServiceRegistration registration, Object service) {
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/eadbfe97/code/core/src/main/java/org/apache/tamaya/core/internal/PriorityServiceComparator.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/PriorityServiceComparator.java b/code/core/src/main/java/org/apache/tamaya/core/internal/PriorityServiceComparator.java
new file mode 100644
index 0000000..c0cfca6
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/PriorityServiceComparator.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.internal;
+
+import javax.annotation.Priority;
+import java.util.Comparator;
+
+/**
+ * Comparator implementation for odering services loaded based on their increasing priority values.
+ */
+public class PriorityServiceComparator implements Comparator<Object> {
+
+ @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 s evaluated. If no such
+ * annotation is present, a default priority is returned (1);
+ *
+ * @param o the instance, not 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 s evaluated.
+ * If no such annotation is present, a default priority is returned (1);
+ *
+ * @param type the type, not null.
+ * @return a priority, by default 1.
+ */
+ public static int getPriority(Class type) {
+ int prio = 1;
+ Priority priority = (Priority)type.getAnnotation(Priority.class);
+ if (priority != null) {
+ prio = priority.value();
+ }
+ return prio;
+ }
+}