TAMAYA-182: Streamlined/unified builder API and impl.
Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/commit/32a1616c Tree: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/tree/32a1616c Diff: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/diff/32a1616c Branch: refs/heads/master Commit: 32a1616cd358059d7e715ce4e0b7cfd4b586d1b1 Parents: 8a8a535 Author: anatole <anat...@apache.org> Authored: Sun Oct 23 15:38:00 2016 +0200 Committer: anatole <anat...@apache.org> Committed: Sun Oct 23 15:38:00 2016 +0200 ---------------------------------------------------------------------- .../apache/tamaya/ConfigurationProvider.java | 10 + .../apache/tamaya/spi/ConfigurationContext.java | 45 ++- .../tamaya/spi/ConfigurationContextBuilder.java | 233 ++++++++++--- .../tamaya/spi/ConfigurationProviderSpi.java | 47 ++- .../tamaya/TestConfigurationProvider.java | 14 + .../internal/DefaultConfigurationContext.java | 127 +++---- .../DefaultConfigurationContextBuilder.java | 349 ++++++++++++++++--- .../internal/DefaultConfigurationProvider.java | 35 +- .../core/internal/PropertyConverterManager.java | 15 +- .../propertysource/SystemPropertySource.java | 1 - .../apache/tamaya/core/ConfigurationTest.java | 6 + jqassistant/serviceloader-rules.xml | 2 +- 12 files changed, 678 insertions(+), 206 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/32a1616c/code/api/src/main/java/org/apache/tamaya/ConfigurationProvider.java ---------------------------------------------------------------------- diff --git a/code/api/src/main/java/org/apache/tamaya/ConfigurationProvider.java b/code/api/src/main/java/org/apache/tamaya/ConfigurationProvider.java index bc4cd13..875f8fc 100644 --- a/code/api/src/main/java/org/apache/tamaya/ConfigurationProvider.java +++ b/code/api/src/main/java/org/apache/tamaya/ConfigurationProvider.java @@ -88,6 +88,16 @@ public final class ConfigurationProvider { } /** + * Creates a new configuration instance based on the given context. + * + * @param context the configuration context, not null. + * @return a new Configuration instance, never null. + */ + public static Configuration createConfiguration(ConfigurationContext context) { + return PROVIDER_SPI.createConfiguration(context); + } + + /** * Get access to the current ConfigurationContext. * * @return the current ConfigurationContext, never null. http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/32a1616c/code/api/src/main/java/org/apache/tamaya/spi/ConfigurationContext.java ---------------------------------------------------------------------- diff --git a/code/api/src/main/java/org/apache/tamaya/spi/ConfigurationContext.java b/code/api/src/main/java/org/apache/tamaya/spi/ConfigurationContext.java index 3a757a0..f631d55 100644 --- a/code/api/src/main/java/org/apache/tamaya/spi/ConfigurationContext.java +++ b/code/api/src/main/java/org/apache/tamaya/spi/ConfigurationContext.java @@ -35,9 +35,30 @@ public interface ConfigurationContext { * This method can be used for programmatically adding {@link PropertySource}s. * It is not needed for normal 'usage' by end users, but only for Extension Developers! * - * @param propertySourcesToAdd the PropertySources to add + * @param propertySources the PropertySources to add + * @deprecated Use {@link ConfigurationContextBuilder} to create a new {@link ConfigurationContext}. + * @see #toBuilder() */ - void addPropertySources(PropertySource... propertySourcesToAdd); + @Deprecated + void addPropertySources(PropertySource... propertySources); + + /** + * This method can be used for programmatically adding {@link PropertyFilter}s. + * It is not needed for normal 'usage' by end users, but only for Extension Developers! + * + * @param propertyFilters the PropertyFilters to add + * @deprecated Use {@link ConfigurationContextBuilder} to create a new {@link ConfigurationContext}. + * @see #toBuilder() + */ + @Deprecated + void addPropertyFilter(PropertyFilter... propertyFilters); + + /** + * Allows to check if a given property source is registered, using its name. + * @param name the property source name. + * @return true, if a property source with the given name is present. + */ + boolean containsPropertySource(String name); /** * This method returns the current list of registered PropertySources ordered via their ordinal. @@ -53,23 +74,25 @@ public interface ConfigurationContext { */ List<PropertySource> getPropertySources(); - -// /** -// * Access a {@link PropertySource} using its (unique) name. -// * @param name the propoerty source's name, not null. -// * @return the propoerty source found, or null. -// */ -// PropertySource getPropertySource(String name); + /** + * Access a {@link PropertySource} using its (unique) name. + * @param name the propoerty source's name, not null. + * @return the propoerty source found, or null. + */ + PropertySource getPropertySource(String name); /** * This method can be used for programmatically adding {@link PropertyConverter}s. * It is not needed for normal 'usage' by end users, but only for Extension Developers! * * @param <T> the type of the type literal - * @param typeToConvert the type which the converter is for + * @param type the type which the converter is for * @param propertyConverter the PropertyConverters to add for this type + * @deprecated Use {@link ConfigurationContextBuilder} to create a new {@link ConfigurationContext}. + * @see #toBuilder() */ - <T> void addPropertyConverter(TypeLiteral<T> typeToConvert, PropertyConverter<T> propertyConverter); + @Deprecated + <T> void addPropertyConverter(TypeLiteral<T> type, PropertyConverter<T> propertyConverter); /** http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/32a1616c/code/api/src/main/java/org/apache/tamaya/spi/ConfigurationContextBuilder.java ---------------------------------------------------------------------- diff --git a/code/api/src/main/java/org/apache/tamaya/spi/ConfigurationContextBuilder.java b/code/api/src/main/java/org/apache/tamaya/spi/ConfigurationContextBuilder.java index 6416959..66a2426 100644 --- a/code/api/src/main/java/org/apache/tamaya/spi/ConfigurationContextBuilder.java +++ b/code/api/src/main/java/org/apache/tamaya/spi/ConfigurationContextBuilder.java @@ -20,7 +20,7 @@ package org.apache.tamaya.spi; import org.apache.tamaya.TypeLiteral; -import java.util.Collection; +import java.util.*; /** * A builder for creating new or adapting instances of {@link ConfigurationContext}. @@ -36,20 +36,13 @@ import java.util.Collection; * {@link org.apache.tamaya.ConfigurationProvider#setConfigurationContext(org.apache.tamaya.spi.ConfigurationContext)}. * */ - -/* @todo This is some Javadoc which is outdated. I am not sure if I can deleted it. The author - * should take care. Oliver B. Fischer, 2015-12-23 - * Since this method can - * throw an UnsupportedOperationException, you should check before if changing the current ConfigurationContext - * programmatically is supported by calling - * {@link org.apache.tamaya.ConfigurationProvider#is}. - */ public interface ConfigurationContextBuilder { /** * Init this builder instance with the given {@link ConfigurationContext} instance. This - * method will replace any existing data in the current builder with the data contained in the given - * {@link ConfigurationContext}. + * method will use any existing property sources, filters, converters and the combination + * policy of the given {@link ConfigurationContext} and initialize the current builder + * with them. * * @param context the {@link ConfigurationContext} instance to be used, not null. * @return this builder, for chaining, never null. @@ -57,43 +50,127 @@ public interface ConfigurationContextBuilder { ConfigurationContextBuilder setContext(ConfigurationContext context); /** - * This method can be used for programmatically adding {@link PropertySource}s. - * It is not needed for normal 'usage' by end users, but only for Extension Developers! + * This method can be used for adding {@link PropertySource}s. + * Hereby the property source is added to the tail of property sources with + * lowest priority regardless of its current ordinal value. To sort the property + * sources based on their ordinals call {@kink #sortPropertySources}. * - * @param propertySourcesToAdd the PropertySources to add + * @param propertySources the PropertySources to add * @return this builder, for chaining, never null. + * @throws IllegalArgumentException If a property source with a given name already + * exists. */ - ConfigurationContextBuilder addPropertySources(PropertySource... propertySourcesToAdd); + ConfigurationContextBuilder addPropertySources(PropertySource... propertySources); /** * This method can be used for programmatically adding {@link PropertySource}s. - * It is not needed for normal 'usage' by end users, but only for Extension Developers! + * Hereby the property source is added to the tail of property sources with + * lowest priority regardless of its current ordinal value. To sort the property + * sources based on their ordinals call {@kink #sortPropertySources}. * - * @param propertySourcesToAdd the PropertySources to add + * @param propertySources the PropertySources to add * @return this builder, for chaining, never null. + * @throws IllegalArgumentException If a property source with a given name already + * exists. */ - ConfigurationContextBuilder addPropertySources(Collection<PropertySource> propertySourcesToAdd); + ConfigurationContextBuilder addPropertySources(Collection<PropertySource> propertySources); /** - * This method can be used for programmatically adding {@link PropertySource}s. - * It is not needed for normal 'usage' by end users, but only for Extension Developers! + * Removes the given property sources, if existing. The existing order of property + * sources is preserved. * - * @param propertySourcesNames the PropertySource names of the sources to remove - * @return this builder, for chaining, never null. + * @param propertySources the property sources to remove, not null. + * @return the builder for chaining. */ - ConfigurationContextBuilder removePropertySources(String... propertySourcesNames); + ConfigurationContextBuilder removePropertySources(PropertySource... propertySources); /** - * This method can be used for programmatically adding {@link PropertySource}s. - * It is not needed for normal 'usage' by end users, but only for Extension Developers! + * Removes the given property sources, if existing. The existing order of property + * sources is preserved. * - * @param propertySourcesNames the PropertySource names of the sources to remove - * @return this builder, for chaining, never null. + * @param propertySources the property sources to remove, not null. + * @return the builder for chaining. + */ + ConfigurationContextBuilder removePropertySources(Collection<PropertySource> propertySources); + + /** + * Access the current chain of property sources. Items at the end of the list have + * precedence/more significance. + * + * @return the property source chain, never null. + */ + List<PropertySource> getPropertySources(); + + /** + * Access the current chain of property filters. Items at the end of the list have + * precedence/more significance. + * + * @return the property source chain, never null. */ - ConfigurationContextBuilder removePropertySources(Collection<String> propertySourcesNames); + List<PropertyFilter> getPropertyFilters(); /** - * Adds the given PropertyFilter instances. + * Access the current registered property converters. + * + * @return the current registered property converters. + */ + Map<TypeLiteral<?>, Collection<PropertyConverter<?>>> getPropertyConverter(); + + /** + * Increases the priority of the given property source, by moving it towards the end + * of the chain of property sources. If the property source given is already at the end + * this method has no effect. This operation does not change any ordinal values. + * + * @param propertySource the property source to be incresed regarding its significance. + * @return the builder for chaining. + * @throws IllegalArgumentException If no such property source exists in the current + * chain. + */ + ConfigurationContextBuilder increasePriority(PropertySource propertySource); + + /** + * Decreases the priority of the given property source, by moving it towards the start + * of the chain of property sources. If the property source given is already the first + * this method has no effect. This operation does not change any ordinal values. + * + * @param propertySource the property source to be decresed regarding its significance. + * @return the builder for chaining. + * @throws IllegalArgumentException If no such property source exists in the current + * chain. + */ + ConfigurationContextBuilder decreasePriority(PropertySource propertySource); + + /** + * Increases the priority of the given property source to be maximal, by moving it to + * the tail of the of property source chain. If the property source given is + * already the last item this method has no effect. This operation does not change + * any ordinal values. + * + * @param propertySource the property source to be maximized regarding its significance. + * @return the builder for chaining. + * @throws IllegalArgumentException If no such property source exists in the current + * chain. + */ + ConfigurationContextBuilder highestPriority(PropertySource propertySource); + + /** + * Decreases the priority of the given property source to be minimal, by moving it to + * the start of the chain of property source chain. If the property source given is + * already the first item this method has no effect. This operation does not change + * any ordinal values. + * + * @param propertySource the property source to be minimized regarding its significance. + * @return the builder for chaining. + * @throws IllegalArgumentException If no such property source exists in the current + * chain. + */ + ConfigurationContextBuilder lowestPriority(PropertySource propertySource); + + /** + * Adds the given PropertyFilter instances, hereby the instances are added + * to the end of the list with highest priority. The ordering of existing + * property filters remains unchanged. To sort the property + * filters call {@kink #sortPropertyFilter}. * * @param filters the filters to add * @return this builder, for chaining, never null. @@ -101,7 +178,10 @@ public interface ConfigurationContextBuilder { ConfigurationContextBuilder addPropertyFilters(PropertyFilter... filters); /** - * Adds the given PropertyFilter instances. + * Adds the given PropertyFilter instances, hereby the instances are added + * to the end of the list with highest priority. The ordering of existing + * property filters remains unchanged. To sort the property + * filters call {@kink #sortPropertyFilter}. * * @param filters the filters to add * @return this builder, for chaining, never null. @@ -109,52 +189,99 @@ public interface ConfigurationContextBuilder { ConfigurationContextBuilder addPropertyFilters(Collection<PropertyFilter> filters); /** - * Removes the given PropertyFilter instances. + * Removes the given PropertyFilter instances, if existing. The order of the remaining + * filters is preserved. * - * @param filters the filters to remove + * @param filters the filter to remove * @return this builder, for chaining, never null. */ ConfigurationContextBuilder removePropertyFilters(PropertyFilter... filters); /** - * Removes the given PropertyFilter instances. + * Removes the given PropertyFilter instances, if existing. The order of the remaining + * filters is preserved. * - * @param filters the filters to remove + * @param filters the filter to remove * @return this builder, for chaining, never null. */ ConfigurationContextBuilder removePropertyFilters(Collection<PropertyFilter> filters); /** - * This method can be used for programmatically adding {@link PropertyConverter}s. - * It is not needed for normal 'usage' by end users, but only for Extension Developers! + * This method can be used for adding {@link PropertyConverter}s. + * Converters are added at the end after any existing converters. + * For converters already registered for the current target type the + * method has no effect. * - * @param <T> the type of the type literal * @param typeToConvert the type for which the converter is for - * @param propertyConverter the PropertyConverters to add for this type + * @param propertyConverters the PropertyConverters to add for this type * @return this builder, for chaining, never null. */ - <T> ConfigurationContextBuilder addPropertyConverter(TypeLiteral<T> typeToConvert, - PropertyConverter<T> propertyConverter); + <T> ConfigurationContextBuilder addPropertyConverters(TypeLiteral<T> typeToConvert, + PropertyConverter<T>... propertyConverters); /** - * Removes the given PropertyConverter instances. + * This method can be used for adding {@link PropertyConverter}s. + * Converters are added at the end after any existing converters. + * For converters already registered for the current target type the + * method has no effect. + * + * @param typeToConvert the type for which the converter is for + * @param propertyConverters the PropertyConverters to add for this type + * @return this builder, for chaining, never null. + */ + <T> ConfigurationContextBuilder addPropertyConverters(TypeLiteral<T> typeToConvert, + Collection<PropertyConverter<T>> propertyConverters); + + /** + * Removes the given PropertyConverter instances for the given type, + * if existing. * * @param typeToConvert the type which the converter is for - * @param converters the converters to remove + * @param propertyConverters the converter to remove * @return this builder, for chaining, never null. */ - ConfigurationContextBuilder removePropertyConverters(TypeLiteral<?> typeToConvert, - PropertyConverter<?>... converters); + <T> ConfigurationContextBuilder removePropertyConverters(TypeLiteral<T> typeToConvert, + PropertyConverter<T>... propertyConverters); /** - * Removes the given PropertyConverter instances. + * Removes the given PropertyConverter instances for the given type, + * if existing. * * @param typeToConvert the type which the converter is for - * @param converters the converters to remove + * @param propertyConverters the converter to remove * @return this builder, for chaining, never null. */ - ConfigurationContextBuilder removePropertyConverters(TypeLiteral<?> typeToConvert, - Collection<PropertyConverter<?>> converters); + <T> ConfigurationContextBuilder removePropertyConverters(TypeLiteral<T> typeToConvert, + Collection<PropertyConverter<T>> propertyConverters); + + /** + * Removes all converters for the given type, which actually renders a given type + * unsupported for type conversion. + * + * @param typeToConvert the type which the converter is for + * @return this builder, for chaining, never null. + */ + ConfigurationContextBuilder removePropertyConverters(TypeLiteral<?> typeToConvert); + + /** + * Sorts the current registered property sources using the given comparator. + * + * NOTE: property sources at the beginning have minimal significance. + * + * @param comparator the comparator to be used, not null. + * @return this instance for chaining. + */ + ConfigurationContextBuilder sortPropertySources(Comparator<PropertySource> comparator); + + /** + * Sorts the current registered property filters using the given comparator. + * + * NOTE: property filters at the beginning have minimal significance. + * + * @param comparator the comparator to be used, not null. + * @return this instance for chaining. + */ + ConfigurationContextBuilder sortPropertyFilter(Comparator<PropertyFilter> comparator); /** * Sets the {@link PropertyValueCombinationPolicy} used to evaluate the final @@ -166,9 +293,15 @@ public interface ConfigurationContextBuilder { ConfigurationContextBuilder setPropertyValueCombinationPolicy(PropertyValueCombinationPolicy policy); /** - * Builds a {@link ConfigurationContext} based on the data set. - * @return final context with the current builder's properties. + * Builds a new {@link ConfigurationContext} based on the data in this builder. The ordering of property + * sources and property filters is not changed, regardless of their ordinals. For ensure a certain + * ordering/significance call {@link #sortPropertyFilter(Comparator)} and/or {@link #sortPropertySources(Comparator)} + * before building the context. + * + * @return the final context to be used to create a configuration. + * @see org.apache.tamaya.ConfigurationProvider#createConfiguration(ConfigurationContext) */ ConfigurationContext build(); } + http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/32a1616c/code/api/src/main/java/org/apache/tamaya/spi/ConfigurationProviderSpi.java ---------------------------------------------------------------------- diff --git a/code/api/src/main/java/org/apache/tamaya/spi/ConfigurationProviderSpi.java b/code/api/src/main/java/org/apache/tamaya/spi/ConfigurationProviderSpi.java index d179d1e..1f473e3 100644 --- a/code/api/src/main/java/org/apache/tamaya/spi/ConfigurationProviderSpi.java +++ b/code/api/src/main/java/org/apache/tamaya/spi/ConfigurationProviderSpi.java @@ -36,6 +36,43 @@ public interface ConfigurationProviderSpi { Configuration getConfiguration(); /** + * Create a {@link Configuration} instance using the given context. The configuration + * created hereby must respect the artifacts provided by its context (property sources, + * filters, converters, policies etc), including their ordering and significance. + * @param context the context to be used, not null. + * @return the corresponding configuration instance. + */ + Configuration createConfiguration(ConfigurationContext context); + + /** + * Creates a new {@link org.apache.tamaya.spi.ConfigurationContextBuilder} instance. + * + * @return a new {@link org.apache.tamaya.spi.ConfigurationContextBuilder}, never null. + */ + ConfigurationContextBuilder getConfigurationContextBuilder(); + + /** + * This method allows to replace the current {@link org.apache.tamaya.Configuration} with a new + * instance. This can be used to update the configuration with a new one, e.g. because some of the + * data has changed and must be updated. It is the responsibility of the ConfigurationProvider to trigger + * corresponding update events for the current {@link org.apache.tamaya.Configuration}. + * + * @param config the new Configuration to be applied. + * @throws java.lang.UnsupportedOperationException if the current provider is read-only. + */ + void setConfiguration(Configuration config); + + /** + * Method that allows to determine if a new {@link org.apache.tamaya.Configuration} can be applied + * programmatically. + * + * @return true, if {@link #setConfiguration(org.apache.tamaya.Configuration)} is supported + * by the current implementation. + * @see #setConfiguration(org.apache.tamaya.Configuration) + */ + boolean isConfigurationSettable(); + + /** * Get access to the current {@link ConfigurationContext}. * * @return the current {@link ConfigurationContext}, never null. @@ -53,7 +90,9 @@ public interface ConfigurationProviderSpi { * * @param context the new ConfigurationContext to be applied. * @throws java.lang.UnsupportedOperationException if the current provider is read-only. + * @deprecated use {@link #setConfiguration(Configuration)} */ + @Deprecated void setConfigurationContext(ConfigurationContext context); /** @@ -63,14 +102,10 @@ public interface ConfigurationProviderSpi { * @return true, if {@link #setConfigurationContext(org.apache.tamaya.spi.ConfigurationContext)} is supported * by the current implementation. * @see #setConfigurationContext(org.apache.tamaya.spi.ConfigurationContext) + * @deprecated use {@link #isConfigurationSettable()} */ + @Deprecated boolean isConfigurationContextSettable(); - /** - * Creates a new {@link org.apache.tamaya.spi.ConfigurationContextBuilder} instance. - * - * @return a new {@link org.apache.tamaya.spi.ConfigurationContextBuilder}, never null. - */ - ConfigurationContextBuilder getConfigurationContextBuilder(); } http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/32a1616c/code/api/src/test/java/org/apache/tamaya/TestConfigurationProvider.java ---------------------------------------------------------------------- diff --git a/code/api/src/test/java/org/apache/tamaya/TestConfigurationProvider.java b/code/api/src/test/java/org/apache/tamaya/TestConfigurationProvider.java index 1c84b83..3c913a1 100644 --- a/code/api/src/test/java/org/apache/tamaya/TestConfigurationProvider.java +++ b/code/api/src/test/java/org/apache/tamaya/TestConfigurationProvider.java @@ -38,6 +38,11 @@ public class TestConfigurationProvider implements ConfigurationProviderSpi { } @Override + public Configuration createConfiguration(ConfigurationContext context) { + return null; + } + + @Override public ConfigurationContext getConfigurationContext() { return null; } @@ -56,4 +61,13 @@ public class TestConfigurationProvider implements ConfigurationProviderSpi { public ConfigurationContextBuilder getConfigurationContextBuilder() { return null; } + + @Override + public void setConfiguration(Configuration config) { + } + + @Override + public boolean isConfigurationSettable() { + return false; + } } http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/32a1616c/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 index a1a2f64..15c6147 100644 --- 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 @@ -25,19 +25,12 @@ 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.*; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.logging.Logger; @@ -73,71 +66,36 @@ public class DefaultConfigurationContext implements ConfigurationContext { * 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. + * Lock for internal synchronization. */ - 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()); + private final ReentrantReadWriteLock propertyFilterLock = new ReentrantReadWriteLock(); - 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()); + propertySources.addAll(builder.propertySources); // 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); + List<PropertyFilter> propertyFilters = new ArrayList<>(builder.getPropertyFilters()); immutablePropertyFilters = Collections.unmodifiableList(propertyFilters); LOG.info("Registered " + immutablePropertyFilters.size() + " property filters: " + immutablePropertyFilters); + // Finally add the converters + for(Map.Entry<TypeLiteral<?>, Collection<PropertyConverter<?>>> en:builder.getPropertyConverter().entrySet()) { + for (PropertyConverter converter : en.getValue()) { + this.propertyConverterManager.register(en.getKey(), converter); + } + } + LOG.info("Registered " + propertyConverterManager.getPropertyConverters().size() + " property converters: " + + propertyConverterManager.getPropertyConverters()); + propertyValueCombinationPolicy = builder.combinationPolicy; if(propertyValueCombinationPolicy==null){ propertyValueCombinationPolicy = ServiceContextManager.getServiceContext().getService(PropertyValueCombinationPolicy.class); @@ -148,23 +106,8 @@ public class DefaultConfigurationContext implements ConfigurationContext { 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; - } + @Deprecated @Override public void addPropertySources(PropertySource... propertySourcesToAdd) { Lock writeLock = propertySourceLock.writeLock(); @@ -180,6 +123,28 @@ public class DefaultConfigurationContext implements ConfigurationContext { } } + + @Deprecated + @Override + public void addPropertyFilter(PropertyFilter... propertyFiltersToAdd) { + Lock writeLock = propertyFilterLock.writeLock(); + try { + writeLock.lock(); + List<PropertyFilter> newPropertyFilters = new ArrayList<>(this.immutablePropertyFilters); + newPropertyFilters.addAll(Arrays.asList(propertyFiltersToAdd)); + Collections.sort(newPropertyFilters, new PropertyFilterComparator()); + + this.immutablePropertyFilters = Collections.unmodifiableList(newPropertyFilters); + } finally { + writeLock.unlock(); + } + } + + @Override + public boolean containsPropertySource(String name) { + return getPropertySource(name)!=null; + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -331,15 +296,15 @@ public class DefaultConfigurationContext implements ConfigurationContext { return immutablePropertySources; } -// @Override -// public PropertySource getPropertySource(String name) { -// for(PropertySource ps:getPropertySources()){ -// if(name.equals(ps.getName())){ -// return ps; -// } -// } -// return null; -// } + @Override + public PropertySource getPropertySource(String name) { + for(PropertySource ps:getPropertySources()){ + if(name.equals(ps.getName())){ + return ps; + } + } + return null; + } @Override public <T> void addPropertyConverter(TypeLiteral<T> typeToConvert, PropertyConverter<T> propertyConverter) { http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/32a1616c/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 index 944a1e0..f3d823e 100644 --- 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 @@ -18,95 +18,243 @@ */ package org.apache.tamaya.core.internal; -import org.apache.tamaya.ConfigException; -import org.apache.tamaya.spi.PropertyConverter; +import org.apache.tamaya.Configuration; 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 java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.logging.Logger; /** * Default implementation of {@link org.apache.tamaya.spi.ConfigurationContextBuilder}. */ public class DefaultConfigurationContextBuilder implements ConfigurationContextBuilder { - final Map<String, PropertySource> propertySources = new HashMap<>(); - final List<PropertyFilter> propertyFilters = new ArrayList<>(); - final Map<TypeLiteral<?>, List<PropertyConverter<?>>> propertyConverters = new HashMap<>(); - PropertyValueCombinationPolicy combinationPolicy; + private static final Logger LOG = Logger.getLogger(DefaultConfigurationContextBuilder.class.getName()); + + public static final Comparator<PropertySource> DEFAULT_PROPERTYSOURCE_COMPARATOR = new PropertySourceComparator(); + public static final Comparator<?> DEFAULT_PROPERTYFILTER_COMPARATOR = new PriorityServiceComparator(); + + List<PropertyFilter> propertyFilters = new ArrayList<>(); + List<PropertySource> propertySources = new ArrayList<>(); + PropertyValueCombinationPolicy combinationPolicy = + PropertyValueCombinationPolicy.DEFAULT_OVERRIDING_COLLECTOR; + Map<TypeLiteral<?>, Collection<PropertyConverter<?>>> propertyConverters = new HashMap<>(); - public DefaultConfigurationContextBuilder(){ + /** + * Flag if the config has already been built. + * Configuration can be built only once + */ + private boolean built; + + + + /** + * Creates a new builder instance. + */ + public DefaultConfigurationContextBuilder() { } - @Override - public ConfigurationContextBuilder setContext(ConfigurationContext context) { - this.propertySources.clear(); + /** + * Creates a new builder instance. + */ + public DefaultConfigurationContextBuilder(ConfigurationContext context) { + this.propertyConverters.putAll(context.getPropertyConverters()); + this.propertyFilters.addAll(context.getPropertyFilters()); for(PropertySource ps:context.getPropertySources()) { - this.propertySources.put(ps.getName(), ps); + addPropertySources(ps); } + this.combinationPolicy = context.getPropertyValueCombinationPolicy(); + } + + /** + * Allows to set configuration context during unit tests. + */ + ConfigurationContextBuilder setConfigurationContext(ConfigurationContext configurationContext) { + checkBuilderState(); + //noinspection deprecation this.propertyFilters.clear(); - this.propertyFilters.addAll(context.getPropertyFilters()); + this.propertyFilters.addAll(configurationContext.getPropertyFilters()); + this.propertySources.clear(); + for(PropertySource ps:configurationContext.getPropertySources()) { + addPropertySources(ps); + } this.propertyConverters.clear(); + this.propertyConverters.putAll(configurationContext.getPropertyConverters()); + this.combinationPolicy = configurationContext.getPropertyValueCombinationPolicy(); + return this; + } + + + @Override + public ConfigurationContextBuilder setContext(ConfigurationContext context) { + checkBuilderState(); this.propertyConverters.putAll(context.getPropertyConverters()); + for(PropertySource ps:context.getPropertySources()){ + this.propertySources.add(ps); + } + this.propertyFilters.addAll(context.getPropertyFilters()); this.combinationPolicy = context.getPropertyValueCombinationPolicy(); return this; } @Override - public ConfigurationContextBuilder addPropertySources(Collection<PropertySource> propertySourcesToAdd) { - for(PropertySource ps:propertySourcesToAdd){ - if(this.propertySources.containsKey(ps.getName())){ - throw new ConfigException("Duplicate PropertySource: " + ps.getName()); + public ConfigurationContextBuilder addPropertySources(PropertySource... sources){ + return addPropertySources(Arrays.asList(sources)); + } + + @Override + public ConfigurationContextBuilder addPropertySources(Collection<PropertySource> sources){ + checkBuilderState(); + for(PropertySource source:sources) { + if (!this.propertySources.contains(source)) { + this.propertySources.add(source); + } + } + return this; + } + + protected DefaultConfigurationContextBuilder loadDefaultPropertyFilters() { + checkBuilderState(); + for(PropertyFilter pf:ServiceContextManager.getServiceContext().getServices(PropertyFilter.class)){ + addPropertyFilters(pf); + } + return this; + } + + protected DefaultConfigurationContextBuilder loadDefaultPropertySources() { + checkBuilderState(); + for(PropertySource ps:ServiceContextManager.getServiceContext().getServices(PropertySource.class)){ + addPropertySources(ps); + } + for(PropertySourceProvider pv:ServiceContextManager.getServiceContext().getServices(PropertySourceProvider.class)){ + for(PropertySource ps:pv.getPropertySources()){ + addPropertySources(ps); } } - for(PropertySource ps:propertySourcesToAdd) { - this.propertySources.put(ps.getName(), ps); + return this; + } + + protected DefaultConfigurationContextBuilder loadDefaultPropertyConverters() { + checkBuilderState(); + for(Map.Entry<TypeLiteral, Collection<PropertyConverter>> en:getDefaultPropertyConverters().entrySet()){ + for(PropertyConverter pc: en.getValue()) { + addPropertyConverters(en.getKey(), pc); + } } return this; } @Override - public ConfigurationContextBuilder addPropertySources(PropertySource... propertySourcesToAdd) { - return addPropertySources(Arrays.asList(propertySourcesToAdd)); + public ConfigurationContextBuilder removePropertySources(PropertySource... propertySources) { + return removePropertySources(Arrays.asList(propertySources)); } @Override - public ConfigurationContextBuilder removePropertySources(Collection<String> propertySourcesToRemove) { - for(String key: propertySourcesToRemove){ - this.propertySources.remove(key); + public ConfigurationContextBuilder removePropertySources(Collection<PropertySource> propertySources) { + checkBuilderState(); + this.propertySources.removeAll(propertySources); + return this; + } + + public PropertySource getPropertySource(String name) { + for(PropertySource ps:propertySources){ + if(ps.getName().equals(name)){ + return ps; + } + } + throw new IllegalArgumentException("No such PropertySource: "+name); + } + + @Override + public List<PropertySource> getPropertySources() { + return this.propertySources; + } + + @Override + public ConfigurationContextBuilder increasePriority(PropertySource propertySource) { + checkBuilderState(); + int index = propertySources.indexOf(propertySource); + if(index<0){ + throw new IllegalArgumentException("No such PropertySource: " + propertySource); + } + if(index<(propertySources.size()-1)){ + propertySources.remove(propertySource); + propertySources.add(index+1, propertySource); } return this; } @Override - public ConfigurationContextBuilder removePropertySources(String... propertySourcesToRemove) { - return removePropertySources(Arrays.asList(propertySourcesToRemove)); + public ConfigurationContextBuilder decreasePriority(PropertySource propertySource) { + checkBuilderState(); + int index = propertySources.indexOf(propertySource); + if(index<0){ + throw new IllegalArgumentException("No such PropertySource: " + propertySource); + } + if(index>0){ + propertySources.remove(propertySource); + propertySources.add(index-1, propertySource); + } + return this; + } + + @Override + public ConfigurationContextBuilder highestPriority(PropertySource propertySource) { + checkBuilderState(); + int index = propertySources.indexOf(propertySource); + if(index<0){ + throw new IllegalArgumentException("No such PropertySource: " + propertySource); + } + if(index<(propertySources.size()-1)){ + propertySources.remove(propertySource); + propertySources.add(propertySource); + } + return this; } @Override - public ConfigurationContextBuilder addPropertyFilters(Collection<PropertyFilter> filters) { - this.propertyFilters.addAll(filters); + public ConfigurationContextBuilder lowestPriority(PropertySource propertySource) { + checkBuilderState(); + int index = propertySources.indexOf(propertySource); + if(index<0){ + throw new IllegalArgumentException("No such PropertySource: " + propertySource); + } + if(index>0){ + propertySources.remove(propertySource); + propertySources.add(0, propertySource); + } return this; } @Override - public ConfigurationContextBuilder addPropertyFilters(PropertyFilter... filters) { + public ConfigurationContextBuilder addPropertyFilters(PropertyFilter... filters){ return addPropertyFilters(Arrays.asList(filters)); } @Override - public ConfigurationContextBuilder removePropertyFilters(Collection<PropertyFilter> filters) { - this.propertyFilters.removeAll(filters); + public ConfigurationContextBuilder addPropertyFilters(Collection<PropertyFilter> filters){ + checkBuilderState(); + for(PropertyFilter f:filters) { + if (!this.propertyFilters.contains(f)) { + this.propertyFilters.add(f); + } + } return this; } @@ -116,38 +264,153 @@ public class DefaultConfigurationContextBuilder implements ConfigurationContextB } @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); - } + public ConfigurationContextBuilder removePropertyFilters(Collection<PropertyFilter> filters) { + checkBuilderState(); + this.propertyFilters.removeAll(filters); return this; } + @Override - public ConfigurationContextBuilder removePropertyConverters(TypeLiteral<?> typeToConvert, PropertyConverter<?>... converters) { + public <T> ConfigurationContextBuilder removePropertyConverters(TypeLiteral<T> typeToConvert, + PropertyConverter<T>... 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); + public <T> ConfigurationContextBuilder removePropertyConverters(TypeLiteral<T> typeToConvert, + Collection<PropertyConverter<T>> converters) { + Collection<PropertyConverter<?>> subConverters = this.propertyConverters.get(typeToConvert); + if(subConverters!=null) { + subConverters.removeAll(converters); + } + return this; + } + + @Override + public ConfigurationContextBuilder removePropertyConverters(TypeLiteral<?> typeToConvert) { + this.propertyConverters.remove(typeToConvert); + return this; + } + + + @Override + public ConfigurationContextBuilder setPropertyValueCombinationPolicy(PropertyValueCombinationPolicy combinationPolicy){ + checkBuilderState(); + this.combinationPolicy = Objects.requireNonNull(combinationPolicy); + return this; + } + + + @Override + public <T> ConfigurationContextBuilder addPropertyConverters(TypeLiteral<T> type, PropertyConverter<T>... propertyConverters){ + checkBuilderState(); + Objects.requireNonNull(type); + Objects.requireNonNull(propertyConverters); + Collection<PropertyConverter<?>> converters = this.propertyConverters.get(type); + if(converters==null){ + converters = new ArrayList<>(); + this.propertyConverters.put(type, converters); + } + for(PropertyConverter<T> propertyConverter:propertyConverters) { + if (!converters.contains(propertyConverter)) { + converters.add(propertyConverter); + } else { + LOG.warning("Converter ignored, already registered: " + propertyConverter); + } } return this; } @Override - public ConfigurationContextBuilder setPropertyValueCombinationPolicy(PropertyValueCombinationPolicy policy) { - this.combinationPolicy = Objects.requireNonNull(policy); + public <T> ConfigurationContextBuilder addPropertyConverters(TypeLiteral<T> type, Collection<PropertyConverter<T>> propertyConverters){ + checkBuilderState(); + Objects.requireNonNull(type); + Objects.requireNonNull(propertyConverters); + Collection<PropertyConverter<?>> converters = this.propertyConverters.get(type); + if(converters==null){ + converters = new ArrayList<>(); + this.propertyConverters.put(type, converters); + } + for(PropertyConverter<T> propertyConverter:propertyConverters) { + if (!converters.contains(propertyConverter)) { + converters.add(propertyConverter); + } else { + LOG.warning("Converter ignored, already registered: " + propertyConverter); + } + } + return this; + } + + private WrappedPropertySource getWrappedPropertySource(PropertySource delegate) { + PropertySource ps = getPropertySource(delegate.getName()); + return WrappedPropertySource.of(ps); + } + + protected ConfigurationContextBuilder loadDefaults() { + checkBuilderState(); + this.combinationPolicy = PropertyValueCombinationPolicy.DEFAULT_OVERRIDING_COLLECTOR; + loadDefaultPropertySources(); + loadDefaultPropertyFilters(); + loadDefaultPropertyConverters(); return this; } + + protected Map<TypeLiteral, Collection<PropertyConverter>> getDefaultPropertyConverters() { + Map<TypeLiteral, Collection<PropertyConverter>> result = new HashMap<>(); + for (PropertyConverter conv : ServiceContextManager.getServiceContext().getServices( + PropertyConverter.class)) { + TypeLiteral target = TypeLiteral.of(TypeLiteral.of(conv.getClass()).getType()); + Collection<PropertyConverter> convList = result.get(target); + if (convList == null) { + convList = new ArrayList<>(); + result.put(target, convList); + } + convList.add(conv); + } + return result; + } + + + /** + * Builds a new configuration based on the configuration of this builder instance. + * + * @return a new {@link Configuration configuration instance}, + * never {@code null}. + */ @Override public ConfigurationContext build() { + checkBuilderState(); + built = true; return new DefaultConfigurationContext(this); } + @Override + public ConfigurationContextBuilder sortPropertyFilter(Comparator<PropertyFilter> comparator) { + Collections.sort(propertyFilters, comparator); + return this; + } + + @Override + public ConfigurationContextBuilder sortPropertySources(Comparator<PropertySource> comparator) { + Collections.sort(propertySources, comparator); + return this; + } + + private void checkBuilderState() { + if (built) { + throw new IllegalStateException("Configuration has already been build."); + } + } + + @Override + public List<PropertyFilter> getPropertyFilters() { + return propertyFilters; + } + + @Override + public Map<TypeLiteral<?>, Collection<PropertyConverter<?>>> getPropertyConverter() { + return Collections.unmodifiableMap(this.propertyConverters); + } } http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/32a1616c/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 index 4330b7e..e03d9ce 100644 --- 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 @@ -24,6 +24,8 @@ import org.apache.tamaya.spi.ConfigurationContextBuilder; import org.apache.tamaya.spi.ConfigurationProviderSpi; import org.apache.tamaya.spi.ServiceContextManager; +import java.util.Objects; + /** * 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} @@ -31,7 +33,11 @@ import org.apache.tamaya.spi.ServiceContextManager; */ public class DefaultConfigurationProvider implements ConfigurationProviderSpi { - private ConfigurationContext context = new DefaultConfigurationContext(); + ConfigurationContext context = new DefaultConfigurationContextBuilder() + .loadDefaultPropertyConverters() + .loadDefaultPropertyFilters() + .loadDefaultPropertySources().build(); + private Configuration config = new DefaultConfiguration(context); @Override @@ -40,23 +46,42 @@ public class DefaultConfigurationProvider implements ConfigurationProviderSpi { } @Override - public ConfigurationContext getConfigurationContext() { - return context; + public Configuration createConfiguration(ConfigurationContext context) { + return new DefaultConfiguration(context); } @Override public ConfigurationContextBuilder getConfigurationContextBuilder() { - return ServiceContextManager.getServiceContext().getService(ConfigurationContextBuilder.class); + return new DefaultConfigurationContextBuilder(); + } + + @Override + public void setConfiguration(Configuration config) { + Objects.requireNonNull(config.getContext()); + this.config = Objects.requireNonNull(config); + this.context = config.getContext(); + } + + @Override + public boolean isConfigurationSettable() { + return true; + } + + @Deprecated + @Override + public ConfigurationContext getConfigurationContext() { + return context; } + @Deprecated @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; } + @Deprecated @Override public boolean isConfigurationContextSettable() { return true; http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/32a1616c/code/core/src/main/java/org/apache/tamaya/core/internal/PropertyConverterManager.java ---------------------------------------------------------------------- diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/PropertyConverterManager.java b/code/core/src/main/java/org/apache/tamaya/core/internal/PropertyConverterManager.java index 9360a35..ab35b90 100644 --- a/code/core/src/main/java/org/apache/tamaya/core/internal/PropertyConverterManager.java +++ b/code/core/src/main/java/org/apache/tamaya/core/internal/PropertyConverterManager.java @@ -112,11 +112,16 @@ public class PropertyConverterManager { try { writeLock.lock(); List converters = List.class.cast(this.converters.get(targetType)); + if(converters!=null && converters.contains(converter)){ + return; + } List<PropertyConverter<?>> newConverters = new ArrayList<>(); if (converters != null) { newConverters.addAll(converters); } - newConverters.add(converter); + if(!newConverters.contains(converter)) { + newConverters.add(converter); + } Collections.sort(newConverters, PRIORITY_COMPARATOR); this.converters.put(targetType, Collections.unmodifiableList(newConverters)); // evaluate transitive closure for all inherited supertypes and implemented interfaces @@ -222,12 +227,6 @@ public class PropertyConverterManager { try { readLock.lock(); addConvertersToList(List.class.cast(this.converters.get(targetType)), converterList); - } finally { - readLock.unlock(); - } - // transitive converter - try { - readLock.lock(); addConvertersToList(List.class.cast(this.transitiveConverters.get(targetType)), converterList); } finally { readLock.unlock(); @@ -242,7 +241,7 @@ public class PropertyConverterManager { readLock.unlock(); } } - if (converterList.isEmpty()) { + if (converterList.isEmpty() && !TypeLiteral.of(String.class).equals(targetType)) { // adding any converters created on the fly, e.g. for enum types. PropertyConverter<T> defaultConverter = createDefaultPropertyConverter(targetType); if (defaultConverter != null) { http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/32a1616c/code/core/src/main/java/org/apache/tamaya/core/propertysource/SystemPropertySource.java ---------------------------------------------------------------------- diff --git a/code/core/src/main/java/org/apache/tamaya/core/propertysource/SystemPropertySource.java b/code/core/src/main/java/org/apache/tamaya/core/propertysource/SystemPropertySource.java index 40576fa..bd568d4 100644 --- a/code/core/src/main/java/org/apache/tamaya/core/propertysource/SystemPropertySource.java +++ b/code/core/src/main/java/org/apache/tamaya/core/propertysource/SystemPropertySource.java @@ -20,7 +20,6 @@ package org.apache.tamaya.core.propertysource; import org.apache.tamaya.spi.PropertySource; import org.apache.tamaya.spi.PropertyValue; -import org.apache.tamaya.spi.PropertyValueBuilder; import java.util.Collections; import java.util.HashMap; http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/32a1616c/code/core/src/test/java/org/apache/tamaya/core/ConfigurationTest.java ---------------------------------------------------------------------- diff --git a/code/core/src/test/java/org/apache/tamaya/core/ConfigurationTest.java b/code/core/src/test/java/org/apache/tamaya/core/ConfigurationTest.java index 98bb29c..3b3b407 100644 --- a/code/core/src/test/java/org/apache/tamaya/core/ConfigurationTest.java +++ b/code/core/src/test/java/org/apache/tamaya/core/ConfigurationTest.java @@ -45,6 +45,12 @@ public class ConfigurationTest { @Test public void testContent(){ + assertNotNull(current().get("name")); + assertNotNull(current().get("name2")); // from default + assertNotNull(current().get("name3")); // overridden default, mapped by filter to name property + assertNotNull(current().get("name4")); // final only + + assertEquals("Robin", current().get("name")); assertEquals("Sabine", current().get("name2")); // from default assertEquals("Mapped to name: Robin", current().get("name3")); // oderridden default, mapped by filter to name property http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/32a1616c/jqassistant/serviceloader-rules.xml ---------------------------------------------------------------------- diff --git a/jqassistant/serviceloader-rules.xml b/jqassistant/serviceloader-rules.xml index 6c69b11..082430a 100644 --- a/jqassistant/serviceloader-rules.xml +++ b/jqassistant/serviceloader-rules.xml @@ -74,7 +74,7 @@ under the License. OR impl.name =~'.*Test\\$.*') AND NOT impl.fqn IN [// All classes of the builder MUST not use the SPI mechanism - 'org.apache.tamaya.builder.ProgrammaticConfigurationContext' + 'org.apache.tamaya.builder.internal.ProgrammaticConfigurationContext' // See TAMAYA-77 and TAMAYA-78, Oliver B. Fischer, 2015-04-25 // 'org.apache.tamaya.core.internal.DefaultConfigurationContextBuilder' ]