tamaya-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From anat...@apache.org
Subject [1/9] incubator-tamaya git commit: TAMAYA-114: Added base module with common SPI implementations.
Date Tue, 06 Oct 2015 07:57:09 GMT
Repository: incubator-tamaya
Updated Branches:
  refs/heads/master be2d6b8e2 -> d0f38b688


TAMAYA-114: Added base module with common SPI implementations.


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

Branch: refs/heads/master
Commit: b4fc83155faa17e4d6a0440f16121bffdef59b87
Parents: be2d6b8
Author: anatole <anatole@apache.org>
Authored: Tue Oct 6 09:45:05 2015 +0200
Committer: anatole <anatole@apache.org>
Committed: Tue Oct 6 09:55:37 2015 +0200

----------------------------------------------------------------------
 modules/spi-support/pom.xml                     |  59 ++++++
 .../tamaya/spisupport/BasePropertySource.java   |  80 +++++++
 .../tamaya/spisupport/DefaultConfiguration.java | 212 +++++++++++++++++++
 .../spisupport/PriorityServiceComparator.java   |  59 ++++++
 .../spisupport/PropertyFilterComparator.java    |  60 ++++++
 .../tamaya/spisupport/PropertyFiltering.java    | 129 +++++++++++
 .../spisupport/PropertySourceComparator.java    |  54 +++++
 .../SimplePropertiesPropertySource.java         |  82 +++++++
 8 files changed, 735 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b4fc8315/modules/spi-support/pom.xml
----------------------------------------------------------------------
diff --git a/modules/spi-support/pom.xml b/modules/spi-support/pom.xml
new file mode 100644
index 0000000..2b2d6b6
--- /dev/null
+++ b/modules/spi-support/pom.xml
@@ -0,0 +1,59 @@
+<!-- 
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy current the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.tamaya.ext</groupId>
+        <artifactId>tamaya-extensions</artifactId>
+        <version>0.2-incubating-SNAPSHOT</version>
+        <relativePath>..</relativePath>
+    </parent>
+
+    <artifactId>tamaya-spisupport</artifactId>
+    <name> Apache Tamaya SPI Support Classes</name>
+    <description>Apache Tamaya Support Classes useful when implementing the Tamaya
SPI or code independent of the core RI
+        implementation.</description>
+    <packaging>jar</packaging>
+
+    <properties>
+        <jdkVersion>1.7</jdkVersion>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.tamaya</groupId>
+            <artifactId>tamaya-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <!-- Test scope only, do not create a code dependency! -->
+        <dependency>
+            <groupId>org.apache.tamaya</groupId>
+            <artifactId>tamaya-core</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+    </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b4fc8315/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/BasePropertySource.java
----------------------------------------------------------------------
diff --git a/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/BasePropertySource.java
b/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/BasePropertySource.java
new file mode 100644
index 0000000..91496ce
--- /dev/null
+++ b/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/BasePropertySource.java
@@ -0,0 +1,80 @@
+/*
+ * 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 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 final int defaultOrdinal;
+
+    /**
+     * Constructor.
+     * @param defaultOrdinal default ordinal that will be used, if no ordinal is provided
with the config.
+     */
+    protected BasePropertySource(int defaultOrdinal){
+        this.defaultOrdinal = defaultOrdinal;
+    }
+
+    /**
+     * Constructor, using a default ordinal of 0.
+     */
+    protected BasePropertySource(){
+        this(0);
+    }
+
+    @Override
+    public int getOrdinal() {
+        String configuredOrdinal = get(TAMAYA_ORDINAL);
+        if(configuredOrdinal!=null){
+            try{
+                return Integer.parseInt(configuredOrdinal);
+            } 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 String get(String key) {
+        return getProperties().get(key);
+    }
+
+    @Override
+    public boolean isScannable(){
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b4fc8315/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfiguration.java
b/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfiguration.java
new file mode 100644
index 0000000..0f938d0
--- /dev/null
+++ b/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfiguration.java
@@ -0,0 +1,212 @@
+/*
+ * 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.TypeLiteral;
+import org.apache.tamaya.spi.ConfigurationContext;
+import org.apache.tamaya.spi.PropertyConverter;
+import org.apache.tamaya.spi.PropertySource;
+import org.apache.tamaya.spi.PropertyValueCombinationPolicy;
+
+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 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;
+
+
+    /**
+     * 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) {
+        return PropertyFiltering.applyFilter(key, evaluteRawValue(key), configurationContext);
+    }
+
+    /**
+     * Evaluates the raw value using the context's PropertyValueCombinationPolicy.
+     * @param key the key, not null.
+     * @return the value, before filtering is applied.
+     */
+    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 org.apache.tamaya.spi.PropertyFilter}.
+     *
+     * @return the final properties.
+     */
+    @Override
+    public Map<String, String> getProperties() {
+        return PropertyFiltering.applyFilters(evaluateUnfilteredMap(), configurationContext);
+    }
+
+    /**
+     * Evaluate all properties, but do not apply filtering on the output.
+     * @return the unfiltered key, value map.
+     */
+    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);
+            for (PropertyConverter<T> converter : converters) {
+                try {
+                    T t = converter.convert(value);
+                    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);
+        }
+        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/b4fc8315/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PriorityServiceComparator.java
----------------------------------------------------------------------
diff --git a/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PriorityServiceComparator.java
b/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PriorityServiceComparator.java
new file mode 100644
index 0000000..8f15696
--- /dev/null
+++ b/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PriorityServiceComparator.java
@@ -0,0 +1,59 @@
+/*
+ * 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;
+
+    @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) {
+        int prio = 1;
+        Priority priority = o.getClass().getAnnotation(Priority.class);
+        if (priority != null) {
+            prio = priority.value();
+        }
+        return prio;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b4fc8315/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertyFilterComparator.java
----------------------------------------------------------------------
diff --git a/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertyFilterComparator.java
b/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertyFilterComparator.java
new file mode 100644
index 0000000..8eedd8f
--- /dev/null
+++ b/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertyFilterComparator.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.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 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);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b4fc8315/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertyFiltering.java
----------------------------------------------------------------------
diff --git a/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertyFiltering.java
b/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertyFiltering.java
new file mode 100644
index 0000000..5fa15fe
--- /dev/null
+++ b/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertyFiltering.java
@@ -0,0 +1,129 @@
+/*
+ * 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 java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+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(){}
+
+    public static String applyFilter(String key, String unfilteredValue, ConfigurationContext
configurationContext) {
+        // Apply filters to values, prevent values filtered to null!
+        for (int i = 0; i < MAX_FILTER_LOOPS; i++) {
+            boolean changed = false;
+            // Apply filters to values, prevent values filtered to null!
+            for (PropertyFilter filter : configurationContext.getPropertyFilters()) {
+                String newValue = filter.filterProperty(key, unfilteredValue);
+                if (newValue != null && !newValue.equals(unfilteredValue)) {
+                    changed = true;
+                    if (LOG.isLoggable(Level.FINEST)) {
+                        LOG.finest("Filter - " + key + ": " + unfilteredValue + " -> "
+ newValue + " by " + filter);
+                    }
+                } else if (unfilteredValue != null && !unfilteredValue.equals(newValue))
{
+                    changed = true;
+                    if (LOG.isLoggable(Level.FINEST)) {
+                        LOG.finest("Filter - " + key + ": " + unfilteredValue + " -> "
+ newValue + " by " + filter);
+                    }
+                }
+                unfilteredValue = newValue;
+            }
+            if (!changed) {
+                LOG.finest("Finishing filter loop, no changes detected.");
+                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.");
+                }
+            }
+        }
+        return unfilteredValue;
+    }
+
+    public static Map<String, String> applyFilters(Map<String, String> inputMap,
ConfigurationContext configurationContext) {
+        Map<String, String> resultMap = new HashMap<>(inputMap);
+        // Apply filters to values, prevent values filtered to null!
+        for (int i = 0; i < MAX_FILTER_LOOPS; i++) {
+            AtomicInteger changes = new AtomicInteger();
+            for (PropertyFilter filter : configurationContext.getPropertyFilters()) {
+                for (Map.Entry<String, String> entry : inputMap.entrySet()) {
+                    final String k = entry.getKey();
+                    final String v = entry.getValue();
+
+                    String newValue = filter.filterProperty(k, v);
+                    if (newValue != null && !newValue.equals(v)) {
+                        changes.incrementAndGet();
+                        LOG.finest("Filter - " + k + ": " + v + " -> " + newValue + "
by " + filter);
+                    } else if (v != null && !v.equals(newValue)) {
+                        changes.incrementAndGet();
+                        LOG.finest("Filter - " + k + ": " + v + " -> " + newValue + "
by " + filter);
+                    }
+                    // Remove null values
+                    if (null != newValue) {
+                        resultMap.put(k, newValue);
+                    }else{
+                        resultMap.remove(k);
+                    }
+                }
+            }
+            if (changes.get() == 0) {
+                LOG.finest("Finishing filter loop, no changes detected.");
+                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.get());
+                }
+                changes.set(0);
+            }
+        }
+        return resultMap;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b4fc8315/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertySourceComparator.java
----------------------------------------------------------------------
diff --git a/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertySourceComparator.java
b/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertySourceComparator.java
new file mode 100644
index 0000000..68473e1
--- /dev/null
+++ b/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertySourceComparator.java
@@ -0,0 +1,54 @@
+/*
+ * 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 java.io.Serializable;
+import java.util.Comparator;
+
+/**
+ * Comparator for ordering of PropertySources based on their ordinal method and class name.
+ */
+public 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);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b4fc8315/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/SimplePropertiesPropertySource.java
----------------------------------------------------------------------
diff --git a/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/SimplePropertiesPropertySource.java
b/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/SimplePropertiesPropertySource.java
new file mode 100644
index 0000000..69c12f8
--- /dev/null
+++ b/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/SimplePropertiesPropertySource.java
@@ -0,0 +1,82 @@
+/*
+ * 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 java.io.InputStream;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+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.
+ */
+public final class SimplePropertiesPropertySource extends BasePropertySource {
+
+    private static final Logger LOGGER = Logger.getLogger(SimplePropertiesPropertySource.class.getName());
+    private URL url;
+    private Map<String, String> properties = new HashMap<>();
+    private final int priority;
+
+    public SimplePropertiesPropertySource(URL url, int priority){
+        this(null, url, priority);
+    }
+
+    public SimplePropertiesPropertySource(String rootContext, URL url, int priority){
+        this.priority = priority;
+        this.url = Objects.requireNonNull(url);
+        try(InputStream is = url.openStream();){
+            Properties props = new Properties();
+            props.load(is);
+            for(Map.Entry en: props.entrySet()){
+                if(rootContext!=null){
+                    String prefix = rootContext;
+                    if(!prefix.endsWith(".")){
+                        prefix += ".";
+                    }
+                    this.properties.put(prefix + en.getKey().toString(), en.getValue().toString());
+                } else{
+                    this.properties.put(en.getKey().toString(), en.getValue().toString());
+                }
+            }
+        }
+        catch(Exception e){
+            LOGGER.log(Level.WARNING, "Failed to read properties from " + url, e);
+        }
+    }
+
+    @Override
+    public int getOrdinal(){
+        return priority;
+    }
+
+    @Override
+    public String getName() {
+        return url.toExternalForm();
+    }
+
+    @Override
+    public Map<String, String> getProperties() {
+        return properties;
+    }
+
+}


Mime
View raw message