You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tamaya.apache.org by an...@apache.org on 2017/12/10 22:03:38 UTC
[15/23] incubator-tamaya git commit: Reimplemented (also simjplified)
Tamaya core completely based on latest JSR API. Moved prior Tamaya API into
compat module.
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/9bc56a38/code/old/api/src/main/java/org/apache/tamaya/spi/ConfigurationContextBuilder.java
----------------------------------------------------------------------
diff --git a/code/old/api/src/main/java/org/apache/tamaya/spi/ConfigurationContextBuilder.java b/code/old/api/src/main/java/org/apache/tamaya/spi/ConfigurationContextBuilder.java
new file mode 100644
index 0000000..17c1bf4
--- /dev/null
+++ b/code/old/api/src/main/java/org/apache/tamaya/spi/ConfigurationContextBuilder.java
@@ -0,0 +1,336 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.spi;
+
+import org.apache.tamaya.TypeLiteral;
+
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A builder for creating new or adapting instances of {@link ConfigurationContext}.
+ * Builders can be obtained in exactly two ways:
+ * <ol>
+ * <li>By accessing a preinitialized builder from an existing {@link ConfigurationContext},
+ * by calling {@link org.apache.tamaya.spi.ConfigurationContext#toBuilder()}.</li>
+ * <li>By accessing an empty builder instance from
+ * {@link org.apache.tamaya.ConfigurationProvider#getConfigurationContextBuilder()}.</li>
+ * </ol>
+ * After all changes are applied to a builder a new {@link ConfigurationContext} instance can
+ * be created and can be applied by calling
+ * {@link org.apache.tamaya.ConfigurationProvider#setConfigurationContext(org.apache.tamaya.spi.ConfigurationContext)}.
+ * @deprecated Use {@link ConfigurationBuilder} instead.
+ */
+@Deprecated
+public interface ConfigurationContextBuilder {
+
+ /**
+ * Init this builder instance with the given {@link ConfigurationContext} instance. This
+ * method will use any existing property sources, filters, converters and the combination
+ * policy of the given {@link ConfigurationContext} and initialize the current builder
+ * with them.
+ *
+ * @param context the {@link ConfigurationContext} instance to be used, not {@code null}.
+ * @return this builder, for chaining, never null.
+ */
+ ConfigurationContextBuilder setContext(ConfigurationContext context);
+
+ /**
+ * This method can be used for adding {@link PropertySource}s.
+ * Hereby the property source is added to the tail of property sources with
+ * lowest priority regardless of its current ordinal value. To sort the property
+ * sources based on their ordinals call {@link #sortPropertySources}.
+ *
+ * @param propertySources the PropertySources to add
+ * @return this builder, for chaining, never null.
+ * @throws IllegalArgumentException If a property source with a given name already
+ * exists.
+ */
+ ConfigurationContextBuilder addPropertySources(PropertySource... propertySources);
+
+ /**
+ * This method can be used for programmatically adding {@link PropertySource}s.
+ * Hereby the property source is added to the tail of property sources with
+ * lowest priority regardless of its current ordinal value. To sort the property
+ * sources based on their ordinals call {@link #sortPropertySources}.
+ *
+ * @param propertySources the PropertySources to add
+ * @return this builder, for chaining, never null.
+ * @throws IllegalArgumentException If a property source with a given name already
+ * exists.
+ */
+ ConfigurationContextBuilder addPropertySources(Collection<PropertySource> propertySources);
+
+ /**
+ * Add all registered (default) property sources to the context built. The sources are ordered
+ * based on their ordinal values and added to the chain of property sources with
+ * higher priority.
+ * @return this builder, for chaining, never null.
+ */
+ ConfigurationContextBuilder addDefaultPropertySources();
+
+ /**
+ * Removes the given property sources, if existing. The existing order of property
+ * sources is preserved.
+ *
+ * @param propertySources the property sources to remove, not {@code null}.
+ * @return the builder for chaining.
+ */
+ ConfigurationContextBuilder removePropertySources(PropertySource... propertySources);
+
+ /**
+ * Removes the given property sources, if existing. The existing order of property
+ * sources is preserved.
+ *
+ * @param propertySources the property sources to remove, not {@code null}.
+ * @return the builder for chaining.
+ */
+ ConfigurationContextBuilder removePropertySources(Collection<PropertySource> propertySources);
+
+ /**
+ * Access the current chain of property sources. Items at the end of the list have
+ * precedence/more significance.
+ *
+ * @return the property source chain, never {@code null}.
+ */
+ List<PropertySource> getPropertySources();
+
+ /**
+ * Access the current chain of property filters. Items at the end of the list have
+ * precedence/more significance.
+ *
+ * @return the property source chain, never {@code null}.
+ */
+ List<PropertyFilter> getPropertyFilters();
+
+ /**
+ * Access the current registered property converters.
+ *
+ * @return the current registered property converters.
+ */
+ Map<TypeLiteral<?>, Collection<PropertyConverter<?>>> getPropertyConverter();
+
+ /**
+ * Increases the priority of the given property source, by moving it towards the end
+ * of the chain of property sources. If the property source given is already at the end
+ * this method has no effect. This operation does not change any ordinal values.
+ *
+ * @param propertySource the property source to be incresed regarding its significance.
+ * @return the builder for chaining.
+ * @throws IllegalArgumentException If no such property source exists in the current
+ * chain.
+ */
+ ConfigurationContextBuilder increasePriority(PropertySource propertySource);
+
+ /**
+ * Decreases the priority of the given property source, by moving it towards the start
+ * of the chain of property sources. If the property source given is already the first
+ * this method has no effect. This operation does not change any ordinal values.
+ *
+ * @param propertySource the property source to be decresed regarding its significance.
+ * @return the builder for chaining.
+ * @throws IllegalArgumentException If no such property source exists in the current
+ * chain.
+ */
+ ConfigurationContextBuilder decreasePriority(PropertySource propertySource);
+
+ /**
+ * Increases the priority of the given property source to be maximal, by moving it to
+ * the tail of the of property source chain. If the property source given is
+ * already the last item this method has no effect. This operation does not change
+ * any ordinal values.
+ *
+ * @param propertySource the property source to be maximized regarding its significance.
+ * @return the builder for chaining.
+ * @throws IllegalArgumentException If no such property source exists in the current
+ * chain.
+ */
+ ConfigurationContextBuilder highestPriority(PropertySource propertySource);
+
+ /**
+ * Decreases the priority of the given property source to be minimal, by moving it to
+ * the start of the chain of property source chain. If the property source given is
+ * already the first item this method has no effect. This operation does not change
+ * any ordinal values.
+ *
+ * @param propertySource the property source to be minimized regarding its significance.
+ * @return the builder for chaining.
+ * @throws IllegalArgumentException If no such property source exists in the current
+ * chain.
+ */
+ ConfigurationContextBuilder lowestPriority(PropertySource propertySource);
+
+ /**
+ * Adds the given PropertyFilter instances, hereby the instances are added
+ * to the end of the list with highest priority. The ordering of existing
+ * property filters remains unchanged. To sort the property
+ * filters call {@link #sortPropertyFilter}.
+ *
+ * @param filters the filters to add
+ * @return this builder, for chaining, never null.
+ */
+ ConfigurationContextBuilder addPropertyFilters(PropertyFilter... filters);
+
+ /**
+ * Adds the given PropertyFilter instances, hereby the instances are added
+ * to the end of the list with highest priority. The ordering of existing
+ * property filters remains unchanged. To sort the property
+ * filters call {@link #sortPropertyFilter}.
+ *
+ * @param filters the filters to add
+ * @return this builder, for chaining, never null.
+ */
+ ConfigurationContextBuilder addPropertyFilters(Collection<PropertyFilter> filters);
+
+ /**
+ * Add all registered (default) property filters to the context built.
+ * @return this builder, for chaining, never null.
+ */
+ ConfigurationContextBuilder addDefaultPropertyFilters();
+
+
+ /**
+ * Removes the given PropertyFilter instances, if existing. The order of the remaining
+ * filters is preserved.
+ *
+ * @param filters the filter to remove
+ * @return this builder, for chaining, never null.
+ */
+ ConfigurationContextBuilder removePropertyFilters(PropertyFilter... filters);
+
+ /**
+ * Removes the given PropertyFilter instances, if existing. The order of the remaining
+ * filters is preserved.
+ *
+ * @param filters the filter to remove
+ * @return this builder, for chaining, never null.
+ */
+ ConfigurationContextBuilder removePropertyFilters(Collection<PropertyFilter> filters);
+
+ /**
+ * This method can be used for adding {@link PropertyConverter}s.
+ * Converters are added at the end after any existing converters.
+ * For converters already registered for the current target type the
+ * method has no effect.
+ *
+ * @param typeToConvert the type for which the converters is for
+ * @param propertyConverters the PropertyConverters to add for this type
+ * @param <T> the target type.
+ * @return this builder, for chaining, never null.
+ */
+ <T> ConfigurationContextBuilder addPropertyConverters(TypeLiteral<T> typeToConvert,
+ @SuppressWarnings("unchecked") PropertyConverter<T>... propertyConverters);
+
+ /**
+ * This method can be used for adding {@link PropertyConverter}s.
+ * Converters are added at the end after any existing converters.
+ * For converters already registered for the current target type the
+ * method has no effect.
+ *
+ * @param typeToConvert the type for which the converters is for
+ * @param propertyConverters the PropertyConverters to add for this type
+ * @param <T> the target type.
+ * @return this builder, for chaining, never null.
+ */
+ <T> ConfigurationContextBuilder addPropertyConverters(TypeLiteral<T> typeToConvert,
+ Collection<PropertyConverter<T>> propertyConverters);
+
+ /**
+ * Add all registered (default) property converters to the context built.
+ * @return this builder, for chaining, never null.
+ */
+ ConfigurationContextBuilder addDefaultPropertyConverters();
+
+ /**
+ * Removes the given PropertyConverter instances for the given type,
+ * if existing.
+ *
+ * @param typeToConvert the type which the converters is for
+ * @param propertyConverters the converters to remove
+ * @param <T> the target type.
+ * @return this builder, for chaining, never null.
+ */
+ <T> ConfigurationContextBuilder removePropertyConverters(TypeLiteral<T> typeToConvert,
+ @SuppressWarnings("unchecked") PropertyConverter<T>... propertyConverters);
+
+ /**
+ * Removes the given PropertyConverter instances for the given type,
+ * if existing.
+ *
+ * @param typeToConvert the type which the converters is for
+ * @param propertyConverters the converters to remove
+ * @param <T> the target type.
+ * @return this builder, for chaining, never null.
+ */
+ <T> ConfigurationContextBuilder removePropertyConverters(TypeLiteral<T> typeToConvert,
+ Collection<PropertyConverter<T>> propertyConverters);
+
+ /**
+ * Removes all converters for the given type, which actually renders a given type
+ * unsupported for type conversion.
+ *
+ * @param typeToConvert the type which the converters is for
+ * @return this builder, for chaining, never null.
+ */
+ ConfigurationContextBuilder removePropertyConverters(TypeLiteral<?> typeToConvert);
+
+ /**
+ * Sorts the current registered property sources using the given comparator.
+ *
+ * NOTE: property sources at the beginning have minimal significance.
+ *
+ * @param comparator the comparator to be used, not {@code null}.
+ * @return this instance for chaining.
+ */
+ ConfigurationContextBuilder sortPropertySources(Comparator<PropertySource> comparator);
+
+ /**
+ * Sorts the current registered property filters using the given comparator.
+ *
+ * NOTE: property filters at the beginning have minimal significance.
+ *
+ * @param comparator the comparator to be used, not {@code null}.
+ * @return this instance for chaining.
+ */
+ ConfigurationContextBuilder sortPropertyFilter(Comparator<PropertyFilter> comparator);
+
+ /**
+ * Sets the {@link PropertyValueCombinationPolicy} used to evaluate the final
+ * property values.
+ *
+ * @param policy the {@link PropertyValueCombinationPolicy} used, not {@code null}.
+ * @return this builder, for chaining, never null.
+ */
+ ConfigurationContextBuilder setPropertyValueCombinationPolicy(PropertyValueCombinationPolicy policy);
+
+ /**
+ * Builds a new {@link ConfigurationContext} based on the data in this builder. The ordering of property
+ * sources and property filters is not changed, regardless of their ordinals. For ensure a certain
+ * ordering/significance call {@link #sortPropertyFilter(Comparator)} and/or {@link #sortPropertySources(Comparator)}
+ * before building the context.
+ *
+ * @return the final context to be used to create a configuration.
+ * @see org.apache.tamaya.ConfigurationProvider#createConfiguration(ConfigurationContext)
+ */
+ ConfigurationContext build();
+
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/9bc56a38/code/old/api/src/main/java/org/apache/tamaya/spi/ConfigurationProviderSpi.java
----------------------------------------------------------------------
diff --git a/code/old/api/src/main/java/org/apache/tamaya/spi/ConfigurationProviderSpi.java b/code/old/api/src/main/java/org/apache/tamaya/spi/ConfigurationProviderSpi.java
new file mode 100644
index 0000000..fb93ab4
--- /dev/null
+++ b/code/old/api/src/main/java/org/apache/tamaya/spi/ConfigurationProviderSpi.java
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.spi;
+
+import org.apache.tamaya.Configuration;
+
+/**
+ * SPI that must be implemented to provide the component that manages all {@link org.apache.tamaya.Configuration}
+ * instances in a system. In SE this may be a true singleton containing exact one {@link org.apache.tamaya.Configuration}
+ * instance, whereas in Java EE and other more complex environments instances may be returned depending the current
+ * runtime context.
+ */
+public interface ConfigurationProviderSpi {
+
+ /**
+ * Access the current {@link org.apache.tamaya.Configuration}.
+ *
+ * @return the current {@link org.apache.tamaya.Configuration} instance, never null.
+ */
+ Configuration getConfiguration();
+
+ /**
+ * Create a {@link Configuration} instance using the given context. The configuration
+ * created hereby must respect the artifacts provided by its context (property sources,
+ * filters, converters, policies etc), including their ordering and significance.
+ * @param context the context to be used, not {@code null}.
+ * @return the corresponding configuration instance.
+ */
+ Configuration createConfiguration(ConfigurationContext context);
+
+ /**
+ * Creates a new {@link org.apache.tamaya.spi.ConfigurationContextBuilder} instance.
+ *
+ * @return a new {@link org.apache.tamaya.spi.ConfigurationContextBuilder}, never null.
+ * @deprecated Will be removed
+ */
+ @Deprecated
+ ConfigurationContextBuilder getConfigurationContextBuilder();
+
+ /**
+ * Creates a new {@link org.apache.tamaya.spi.ConfigurationBuilder} instance.
+ *
+ * @return a new {@link org.apache.tamaya.spi.ConfigurationBuilder}, never null.
+ */
+ ConfigurationBuilder getConfigurationBuilder();
+
+ /**
+ * This method allows to replace the current {@link org.apache.tamaya.Configuration} with a new
+ * instance. This can be used to update the configuration with a new one, e.g. because some of the
+ * data has changed and must be updated. It is the responsibility of the ConfigurationProvider to trigger
+ * corresponding update events for the current {@link org.apache.tamaya.Configuration}.
+ *
+ * @param config the new Configuration to be applied.
+ * @throws java.lang.UnsupportedOperationException if the current provider is read-only.
+ */
+ void setConfiguration(Configuration config);
+
+ /**
+ * Method that allows to determine if a new {@link org.apache.tamaya.Configuration} can be applied
+ * programmatically.
+ *
+ * @return true, if {@link #setConfiguration(org.apache.tamaya.Configuration)} is supported
+ * by the current implementation.
+ * @see #setConfiguration(org.apache.tamaya.Configuration)
+ */
+ default boolean isConfigurationSettable(){
+ return true;
+ }
+
+ /**
+ * Get access to the current {@link ConfigurationContext}.
+ *
+ * @return the current {@link ConfigurationContext}, never null.
+ * @deprecated Will be removed in favour of {@link Configuration#getContext()}.
+ */
+ @Deprecated
+ default ConfigurationContext getConfigurationContext(){
+ return getConfiguration().getContext();
+ }
+
+ /**
+ * This method allows to replace the current {@link org.apache.tamaya.spi.ConfigurationContext} with a new
+ * instance. This can be used to update the context with a new one, e.g. because some of the configuration
+ * data has changed and must be updated. It is the responsibility of the ConfigurationProvider to trigger
+ * corresponding update event for the current {@link org.apache.tamaya.spi.ConfigurationContext} or
+ * {@link org.apache.tamaya.Configuration}.
+ *
+ * @param context the new ConfigurationContext to be applied.
+ * @throws java.lang.UnsupportedOperationException if the current provider is read-only.
+ * @deprecated use {@link #setConfiguration(Configuration)}
+ */
+ @Deprecated
+ default void setConfigurationContext(ConfigurationContext context){
+ setConfiguration(createConfiguration(context));
+ }
+
+ /**
+ * Method that allows to determine if a new {@link org.apache.tamaya.spi.ConfigurationContext} can be applied
+ * programmatically.
+ *
+ * @return true, if {@link #setConfigurationContext(org.apache.tamaya.spi.ConfigurationContext)} is supported
+ * by the current implementation.
+ * @see #setConfigurationContext(org.apache.tamaya.spi.ConfigurationContext)
+ * @deprecated use {@link #isConfigurationSettable()}
+ */
+ @Deprecated
+ default boolean isConfigurationContextSettable(){
+ return isConfigurationSettable();
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/9bc56a38/code/old/api/src/main/java/org/apache/tamaya/spi/ConversionContext.java
----------------------------------------------------------------------
diff --git a/code/old/api/src/main/java/org/apache/tamaya/spi/ConversionContext.java b/code/old/api/src/main/java/org/apache/tamaya/spi/ConversionContext.java
new file mode 100644
index 0000000..ac8de68
--- /dev/null
+++ b/code/old/api/src/main/java/org/apache/tamaya/spi/ConversionContext.java
@@ -0,0 +1,267 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.spi;
+
+import org.apache.tamaya.Configuration;
+import org.apache.tamaya.TypeLiteral;
+
+import java.lang.reflect.AnnotatedElement;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * A conversion context containing all the required values for implementing conversion. Use the included #Builder
+ * for creating new instances of. This class is thread-safe to use. Adding supported formats is synchronized.
+ * @see PropertyConverter
+ */
+public class ConversionContext {
+
+ private final Configuration configuration;
+ private final String key;
+ private final TypeLiteral<?> targetType;
+ private final AnnotatedElement annotatedElement;
+ private final List<String> supportedFormats = new ArrayList<>();
+ private final ConfigurationContext configurationContext;
+
+ /**
+ * Private constructor used from builder.
+ * @param builder the builder, not {@code null}.
+ */
+ protected ConversionContext(Builder builder){
+ this.key = builder.key;
+ this.annotatedElement = builder.annotatedElement;
+ this.targetType = builder.targetType;
+ this.supportedFormats.addAll(builder.supportedFormats);
+ this.configuration = builder.configuration;
+ this.configurationContext = builder.configurationContext;
+ }
+
+ /**
+ * Get the key accessed. This information is very useful to evaluate additional metadata needed to determine/
+ * control further aspects of the conversion.
+ * @return the key. This may be null in case where a default value has to be converted and no unique underlying
+ * key/value configuration is present.
+ */
+ public String getKey(){
+ return key;
+ }
+
+ /**
+ * Get the target type required.
+ * @return the target type required.
+ */
+ public TypeLiteral<?> getTargetType(){
+ return targetType;
+ }
+
+ /**
+ * Get the annotated element, if conversion is performed using injection mechanisms.
+ * @return the annotated element, or {@code null}.
+ */
+ public AnnotatedElement getAnnotatedElement(){
+ return annotatedElement;
+ }
+
+ /**
+ * Get the configuration, which is targeted.
+ * @return the configuration instance, or {@code null}.
+ */
+ public Configuration getConfiguration(){
+ return configuration;
+ }
+
+ /**
+ * Allows to add information on the supported/tried formats, which can be shown to the user, especially when
+ * conversion failed. Adding of formats is synchronized, all formats are added in order to the overall list.
+ * This means formats should be passed in order of precedence.
+ * @param converterType the converters, which implements the formats provided.
+ * @param formatDescriptors the format descriptions in a human readable form, e.g. as regular expressions.
+ */
+ public void addSupportedFormats(@SuppressWarnings("rawtypes") Class<? extends PropertyConverter> converterType, String... formatDescriptors){
+ synchronized (supportedFormats){
+ for(String format: formatDescriptors) {
+ supportedFormats.add(format + " (" + converterType.getSimpleName() + ")");
+ }
+ }
+ }
+
+ /**
+ * Get the supported/tried formats in precedence order. The contents of this method depends on the
+ * {@link PropertyConverter} instances involved in a conversion.
+ * @return the supported/tried formats, never {@code null}.
+ */
+ public List<String> getSupportedFormats(){
+ synchronized (supportedFormats){
+ return new ArrayList<>(supportedFormats);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "ConversionContext{" +
+ "configuration=" + configuration +
+ ", key='" + key + '\'' +
+ ", targetType=" + targetType +
+ ", annotatedElement=" + annotatedElement +
+ ", supportedFormats=" + supportedFormats +
+ '}';
+ }
+
+ public ConfigurationContext getConfigurationContext() {
+ return configurationContext;
+ }
+
+ /**
+ * Builder to create new instances of {@link ConversionContext}.
+ */
+ public static final class Builder{
+ /** The backing configuration. */
+ private Configuration configuration;
+ /** The configuration context. */
+ private ConfigurationContext configurationContext;
+ /** The accessed key, or null. */
+ private String key;
+ /** The target type. */
+ private TypeLiteral<?> targetType;
+ /** The injection target (only set with injection used). */
+ private AnnotatedElement annotatedElement;
+ /** The ordered list of formats tried. */
+ private final Set<String> supportedFormats = new HashSet<>();
+
+ /**
+ * Creates a new Builder instance.
+ * @param targetType the target type
+ */
+ public Builder(TypeLiteral<?> targetType) {
+ this(null, null, null, targetType);
+ }
+
+ /**
+ * Creates a new Builder instance.
+ * @param key the requested key, may be null.
+ * @param targetType the target type
+ */
+ public Builder(String key, TypeLiteral<?> targetType) {
+ this(null, null, key, targetType);
+ }
+
+ /**
+ * Creates a new Builder instance.
+ * @param configuration the configuration, not {@code null}.
+ * @param configurationContext configuration context, not {@code null}.
+ * @param key the requested key, may be {@code null}.
+ * @param targetType the target type
+ */
+ public Builder(Configuration configuration, ConfigurationContext configurationContext, String key, TypeLiteral<?> targetType){
+ this.key = key;
+ this.configuration = configuration;
+ this.configurationContext = configurationContext;
+ this.targetType = Objects.requireNonNull(targetType);
+ }
+
+ /**
+ * Sets the key.
+ * @param key the key, not {@code null}.
+ * @return the builder instance, for chaining
+ */
+ public Builder setKey(String key){
+ this.key = Objects.requireNonNull(key);
+ return this;
+ }
+
+ /**
+ * Sets the configuration.
+ * @param configuration the configuration, not {@code null}
+ * @return the builder instance, for chaining
+ */
+ public Builder setConfiguration(Configuration configuration){
+ this.configuration = Objects.requireNonNull(configuration);
+ return this;
+ }
+
+ /**
+ * Sets the configuration.
+ * @param configurationContext the configuration, not {@code null}
+ * @return the builder instance, for chaining
+ */
+ public Builder setConfigurationContext(ConfigurationContext configurationContext){
+ this.configurationContext = Objects.requireNonNull(configurationContext);
+ return this;
+ }
+
+ /**
+ * Sets the annotated element, when configuration is injected.
+ * @param annotatedElement the annotated element, not {@code null}
+ * @return the builder instance, for chaining
+ */
+ public Builder setAnnotatedElement(AnnotatedElement annotatedElement){
+ this.annotatedElement = Objects.requireNonNull(annotatedElement);
+ return this;
+ }
+
+ /**
+ * Sets the target type explicitly. This is required in some rare cases, e.g. injection of {@code Provider}
+ * instances, where the provider's result type must be produced.
+ * @param targetType the
+ * @return the builder for chaining.
+ */
+ public Builder setTargetType(@SuppressWarnings("rawtypes") TypeLiteral targetType) {
+ this.targetType = Objects.requireNonNull(targetType);
+ return this;
+ }
+
+ /**
+ * Add the formats provided by a {@link PropertyConverter}. This method should be called by each converters
+ * performing/trying conversion, so the user can be given feedback on the supported formats on failure.
+ * @param converterType the converters type, not {@code null}.
+ * @param formatDescriptors the formats supported in a human readable form, e.g. as regular expressions.
+ * @return the builder instance, for chaining
+ */
+ public Builder addSupportedFormats(@SuppressWarnings("rawtypes") Class<? extends PropertyConverter> converterType, String... formatDescriptors){
+ for(String format: formatDescriptors) {
+ supportedFormats.add(format + " (" + converterType.getSimpleName() + ")");
+ }
+ return this;
+ }
+
+ /**
+ * Builds a new context instance.
+ * @return a new context, never null.
+ */
+ public ConversionContext build(){
+ return new ConversionContext(this);
+ }
+
+ @Override
+ public String toString() {
+ return "Builder{" +
+ "configuration=" + configuration +
+ "context=" + configurationContext +
+ ", key='" + key + '\'' +
+ ", targetType=" + targetType +
+ ", annotatedElement=" + annotatedElement +
+ ", supportedFormats=" + supportedFormats +
+ '}';
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/9bc56a38/code/old/api/src/main/java/org/apache/tamaya/spi/Experimental.java
----------------------------------------------------------------------
diff --git a/code/old/api/src/main/java/org/apache/tamaya/spi/Experimental.java b/code/old/api/src/main/java/org/apache/tamaya/spi/Experimental.java
new file mode 100644
index 0000000..9831820
--- /dev/null
+++ b/code/old/api/src/main/java/org/apache/tamaya/spi/Experimental.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.spi;
+
+import java.lang.annotation.*;
+
+/**
+ * This is a simple annotation for flaging out functionality or features the Tamaya team is not sure if it is already
+ * stabilized, so use it with some caution.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Inherited
+@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.FIELD,
+ ElementType.TYPE})
+public @interface Experimental {
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/9bc56a38/code/old/api/src/main/java/org/apache/tamaya/spi/FilterContext.java
----------------------------------------------------------------------
diff --git a/code/old/api/src/main/java/org/apache/tamaya/spi/FilterContext.java b/code/old/api/src/main/java/org/apache/tamaya/spi/FilterContext.java
new file mode 100644
index 0000000..2851697
--- /dev/null
+++ b/code/old/api/src/main/java/org/apache/tamaya/spi/FilterContext.java
@@ -0,0 +1,140 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.spi;
+
+import org.apache.tamaya.Configuration;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * A filter context containing all the required values for implementing filtering.
+ *
+ * @see PropertyFilter
+ */
+public class FilterContext {
+ /** The key. */
+ private final PropertyValue value;
+ /** The current context. */
+ private final ConfigurationContext context;
+ @Experimental
+ private Map<String, PropertyValue> configEntries = new HashMap<>();
+ @Experimental
+ private boolean singlePropertyScoped;
+
+
+ /**
+ * Creates a new FilterContext, for filtering of a multi value access
+ * using {@link Configuration#getProperties()}.
+ *
+ * @param value the value under evaluation, not {@code null}.
+ * @param configEntries the raw configuration data available in the
+ * current evaluation context, not {@code null}.
+ * @param context the current context, not {@code null}.
+ */
+ public FilterContext(PropertyValue value, Map<String,PropertyValue> configEntries, ConfigurationContext context) {
+ Objects.requireNonNull(value, "Value must not be null.");
+ Objects.requireNonNull(configEntries, "Initial configuration entries must be not null.");
+ Objects.requireNonNull(context, "Context must be not null.");
+
+ this.singlePropertyScoped = false;
+ this.value = Objects.requireNonNull(value);
+ this.context = Objects.requireNonNull(context);
+ this.configEntries.putAll(configEntries);
+ this.configEntries = Collections.unmodifiableMap(this.configEntries);
+ }
+
+ /**
+ * Creates a new FilterContext, for filtering of a single value access
+ * using {@link Configuration#getProperties()}.
+ * @param value the value under evaluation, not {@code null}.
+ * @param context the current context, not {@code null}.
+ */
+ public FilterContext(PropertyValue value, ConfigurationContext context) {
+ Objects.requireNonNull(value, "Value must not be null.");
+ Objects.requireNonNull(context, "Context must be not null.");
+
+ this.singlePropertyScoped = true;
+ this.context = Objects.requireNonNull(context);
+ this.value = Objects.requireNonNull(value);
+ this.configEntries = Collections.unmodifiableMap(this.configEntries);
+ }
+
+ /**
+ * Get the current context.
+ * @return the current context, not {@code null}.
+ */
+ public ConfigurationContext getContext(){
+ return context;
+ }
+
+ /**
+ * Get the property value under evaluation. This information is very useful to evaluate additional metadata needed to determine/
+ * control further aspects of the conversion.
+ *
+ * @return the key. This may be null in case where a default value has to be converted and no unique underlying
+ * key/value configuration is present.
+ */
+ public PropertyValue getProperty() {
+ return value;
+ }
+
+ /**
+ * Method that determines if filtering is done for a single property accessed, or as part of call to
+ * {@code getProperties()}.
+ * @return true, if its scoped to a single property accessed.
+ */
+ @Experimental
+ public boolean isSinglePropertyScoped(){
+ return singlePropertyScoped;
+ }
+
+ /**
+ * This map contains the following keys:
+ * <ul>
+ * <li>the original value <b>before</b> any filters were applied on it.</li>
+ * <li>all values starting with an {@code _<key>.}, for example {@code a.value}
+ * may have a map set with {@code a.value} (oringinal value), {@code _a.value.origin,
+ * _a.value.type, etc}. The exact contents is determine by the {@link PropertySource}s
+ * active.</li>
+ * </ul>
+ * Also important to know is that this map given contains all the evaluated raw entries, regardless
+ * of the filters that are later applied. This ensures that met-information required by one filter is
+ * not hidden by another filter, because of an invalid filter ordering. In other words filters may remove
+ * key/value pairs, e.g. fir security reasons, by returning {@code null}, but the values in the raw map
+ * passed as input to the filter process will not be affected by any such removal (but the final properties
+ * returned are affected, of course).
+ *
+ * Finally, when a single property is accessed, e.g. by calling {@code Configuration.get(String)}.
+ *
+ * @return the configuration instance, or null.
+ */
+ @Experimental
+ public Map<String, PropertyValue> getConfigEntries() {
+ return configEntries;
+ }
+
+ @Override
+ public String toString() {
+ return "FilterContext{value='" + value + "', configEntries=" + configEntries.keySet() + '}';
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/9bc56a38/code/old/api/src/main/java/org/apache/tamaya/spi/PropertyConverter.java
----------------------------------------------------------------------
diff --git a/code/old/api/src/main/java/org/apache/tamaya/spi/PropertyConverter.java b/code/old/api/src/main/java/org/apache/tamaya/spi/PropertyConverter.java
new file mode 100644
index 0000000..ab96b6b
--- /dev/null
+++ b/code/old/api/src/main/java/org/apache/tamaya/spi/PropertyConverter.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.spi;
+
+/**
+ * Interface for an property that converts a configured String into something else.
+ * This is used for implementing type conversion from a property (String) to a certain target
+ * type. Hereby the target type can be multi-value (e.g. collections) or complex if needed.
+ *
+ * @param <T> the type of the type literal
+ */
+@FunctionalInterface
+public interface PropertyConverter<T>{
+
+ /**
+ * Convert the given configuration keys from its String representation into the required target type.
+ * The context instance passed also allows to add a list of supported formats, which is very handy in case a
+ * value could not be converted. This list of supported formats can then shown to the user to give some hints
+ * how a value could be configured.
+ *
+ * @param value configuration key that needs to be converted
+ * @param context the {@link ConversionContext}, containing the String value and the requested configuration key.
+ * @return converted keys
+ * @see ConversionContext#addSupportedFormats(Class, String...)
+ */
+ T convert(String value, ConversionContext context);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/9bc56a38/code/old/api/src/main/java/org/apache/tamaya/spi/PropertyFilter.java
----------------------------------------------------------------------
diff --git a/code/old/api/src/main/java/org/apache/tamaya/spi/PropertyFilter.java b/code/old/api/src/main/java/org/apache/tamaya/spi/PropertyFilter.java
new file mode 100644
index 0000000..3054496
--- /dev/null
+++ b/code/old/api/src/main/java/org/apache/tamaya/spi/PropertyFilter.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.spi;
+
+
+/**
+ * <p>Interface for filtering the current map of properties during the evaluation of the chain of PropertySources.
+ * Filters can be registered using the {@link org.apache.tamaya.spi.ServiceContext}. The ordinal
+ * hereby is defined by the corresponding {@code @Priority} annotation.</p>
+ * <p>Filters </p>
+ */
+@FunctionalInterface
+public interface PropertyFilter {
+
+ /**
+ * <p>Maps the current {@code valueToBeFiltered} value to a new value. The resulting value will be used as the result
+ * passed to the user.</p>
+ * <p>If a filter is currently not available, it should just pass the input map to the method's
+ * output.</p>
+ * <p>Returning {@code null} will remove the entry.</p>
+ * <h3>Implementation specification</h3>
+ * Implementations of this class must be
+ * <ul>
+ * <li>reentrant</li>
+ * <li>thread-safe</li>
+ * </ul>
+ * @param value the value to be filtered, which also can be {@code null} if removed by another filter.
+ * @param context the filter context, not {@code null}.
+ * @return the filtered value, or {@code null} if the value should be removed alltogether.
+ * @see PropertyValue
+ * @see PropertyValueBuilder
+ */
+ PropertyValue filterProperty(PropertyValue value, FilterContext context);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/9bc56a38/code/old/api/src/main/java/org/apache/tamaya/spi/PropertySource.java
----------------------------------------------------------------------
diff --git a/code/old/api/src/main/java/org/apache/tamaya/spi/PropertySource.java b/code/old/api/src/main/java/org/apache/tamaya/spi/PropertySource.java
new file mode 100644
index 0000000..864cd95
--- /dev/null
+++ b/code/old/api/src/main/java/org/apache/tamaya/spi/PropertySource.java
@@ -0,0 +1,174 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+package org.apache.tamaya.spi;
+
+
+import org.apache.tamaya.Configuration;
+
+import java.util.Collections;
+import java.util.Map;
+
+
+/**
+ * <p>This interface models a provider that serves configuration properties. The contained
+ * properties may be read from a Map of single or several sources (composite).
+ * PropertySources are the building blocks of the final configuration. </p>
+ * <h3>Implementation Requirements</h3>
+ * <p>Implementations of this interface must be</p>
+ * <ul>
+ * <li>Thread safe.</li>
+ * </ul>
+ *
+ * <p>A PropertySourceProvider will get picked up via the
+ * {@link java.util.ServiceLoader} mechanism and can be registered via
+ * {@code META-INF/services/org.apache.tamaya.spi.PropertySource}
+ * </p>
+ * <p>
+ * If you like to register multiple PropertySources at the same time
+ * you can use the {@link org.apache.tamaya.spi.PropertySourceProvider}
+ * interface.
+ * </p>
+ */
+public interface PropertySource {
+
+ /**
+ * property name to override default tamaya ordinals
+ */
+ String TAMAYA_ORDINAL = "tamaya.ordinal";
+
+ /**
+ * A resusable instance of an empty PropertySource.
+ */
+ PropertySource EMPTY = new PropertySource() {
+
+ @Override
+ public int getOrdinal() {
+ return Integer.MIN_VALUE;
+ }
+
+ @Override
+ public String getName() {
+ return "<empty>";
+ }
+
+ @Override
+ public PropertyValue get(String key) {
+ return null;
+ }
+
+ @Override
+ public Map<String, PropertyValue> getProperties() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public boolean isScannable() {
+ return false;
+ }
+
+ @Override
+ public String toString(){
+ return "PropertySource.EMPTY";
+ }
+ };
+
+
+ /**
+ * The ordinal value is the default ordering parameter which definines the default order of
+ * auto-discovered property sources. Ordering of property sources is important since values
+ * from property sources with higher ordinal values override values from less significant
+ * property sources.
+ *
+ * By default Tamaya includes the following property sources:
+ * <ol>
+ * <li>Properties file values (/META-INF/javaconfiguration.properties) (ordinal 100)</li>
+ * <li>JNDI values (ordinal 200, only when adding the {@code tamaya-jndi} extension module)</li>
+ * <li>Environment properties (ordinal 300)</li>
+ * <li>System properties (ordinal 1000)</li>
+ * </ol>
+ *
+ * <p><b>Important Hints for custom implementations</b>:</p>
+ * <p>
+ * If a custom implementation should be invoked <b>before</b> the default implementations, use a value > 1000
+ * </p>
+ * <p>
+ * If a custom implementation should be invoked <b>after</b> the default implementations, use a value < 100
+ * </p>
+ *
+ * <p>Reordering of the default order of the config-sources:</p>
+ * <p>Example: If the properties file/s should be used <b>before</b> the other implementations,
+ * you have to configure an ordinal > 1000. That means, you have to add e.g. tamaya.ordinal=401 to
+ * /META-INF/javaconfiguration.properties . Hint: In case of property files every file is handled as independent
+ * config-source, but all of them have ordinal 400 by default (and can be reordered in a fine-grained manner.</p>
+ *
+ * In cases where it is not possible to change a config sources ordinal value, you may have several options:
+ * <ul>
+ * <li>you can register an alternate implementation of {@link PropertyValueCombinationPolicy}.</li>
+ * <li>you can use a {@link ConfigurationContextBuilder} to redefine the source order and finally use
+ * {@link org.apache.tamaya.ConfigurationProvider#setConfiguration(Configuration)} to
+ * change the current default {@link Configuration}.</li>
+ * <li>finally, the imeplementor of this API may define alternate mechanism to reconfigure an ordinal
+ * in a vendor specific way.</li>
+ * </ul>
+ * @return the 'importance' aka ordinal of the configured values. The higher, the more important.
+ */
+ int getOrdinal();
+
+
+ /**
+ * Get the name of the property source. The name should be unique for the type of source, whereas the id is used
+ * to ensure unique identity, either locally or remotely.
+ * @return the configuration's name, never {@code null}.
+ */
+ String getName();
+
+ /**
+ * Access a property.
+ *
+ * @param key the property's key, not {@code null}.
+ * @return the property value map, where {@code map.get(key) == value}, including also any metadata. In case a
+ * value is null, simply return {@code null}.
+ */
+ PropertyValue get(String key);
+
+ /**
+ * Access the current properties as Set. The resulting Map may not return all items accessible, e.g.
+ * when the underlying storage does not support iteration of its entries.
+ {@code null}
+ * @return the corresponding map, never null.
+ */
+ Map<String, PropertyValue> getProperties();
+
+ /**
+ * Determines if this config source can be scanned for its list of properties.
+ *
+ * <p>
+ * PropertySources which are not scannable might not be able to find all the
+ * configured values to provide via {@link #getProperties()}. This might happen
+ * if the underlying storage doesn't support listing.
+ * </p>
+ *
+ * @return {@code true} if this PropertySource can be scanned for its list of properties,
+ * {@code false} if it cannot/should not be scanned.
+ */
+ default boolean isScannable(){
+ return true;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/9bc56a38/code/old/api/src/main/java/org/apache/tamaya/spi/PropertySourceProvider.java
----------------------------------------------------------------------
diff --git a/code/old/api/src/main/java/org/apache/tamaya/spi/PropertySourceProvider.java b/code/old/api/src/main/java/org/apache/tamaya/spi/PropertySourceProvider.java
new file mode 100644
index 0000000..3f7beea
--- /dev/null
+++ b/code/old/api/src/main/java/org/apache/tamaya/spi/PropertySourceProvider.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.spi;
+
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * <p>Implement this interfaces to provide a PropertySource provider which
+ * is able to register multiple PropertySources. This is e.g. needed if
+ * there are multiple property files of a given config file name.</p>
+ *
+ * <p>If a PropertySource like JNDI only exists once, then there is no need
+ * to implement it via the PropertySourceProvider but should directly
+ * expose a {@link PropertySource}.</p>
+ *
+ * <p>A PropertySourceProvider will get picked up via the
+ * {@link java.util.ServiceLoader} mechanism and must get registered via
+ * META-INF/services/org.apache.tamaya.spi.PropertySourceProvider</p>
+ */
+@FunctionalInterface
+public interface PropertySourceProvider {
+
+ /**
+ * A resusable instance of an empty PropertySource.
+ */
+ PropertySourceProvider EMPTY = new PropertySourceProvider() {
+
+ @Override
+ public Collection<PropertySource> getPropertySources() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public String toString(){
+ return "PropertySourceProvider(empty)";
+ }
+ };
+
+ /**
+ * @return For each e.g. property file, we return a single PropertySource
+ * or an empty list if no PropertySource exists.
+ */
+ Collection<PropertySource> getPropertySources();
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/9bc56a38/code/old/api/src/main/java/org/apache/tamaya/spi/PropertyValue.java
----------------------------------------------------------------------
diff --git a/code/old/api/src/main/java/org/apache/tamaya/spi/PropertyValue.java b/code/old/api/src/main/java/org/apache/tamaya/spi/PropertyValue.java
new file mode 100644
index 0000000..c538de7
--- /dev/null
+++ b/code/old/api/src/main/java/org/apache/tamaya/spi/PropertyValue.java
@@ -0,0 +1,232 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.spi;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * Class modelling the result of a request for a property value. A property value is basically identified by its key.
+ * There might be reasons, where one want to further analyze, which PropertySources provided a value and which not, so
+ * it is possible to create a PropertyValue with a null value. Nevertheless in all cases the provider source (typically
+ * the name of the PropertySource) must be set.
+ */
+public final class PropertyValue implements Serializable{
+ private static final long serialVersionUID = 1L;
+ /** The requested key. */
+ private String key;
+ /** The value. */
+ private String value;
+ /** The source of the value. */
+ private String source;
+ /** Additional metadata provided by the provider. */
+ private Map<String,String> metaEntries = new HashMap<>();
+
+ PropertyValue(PropertyValueBuilder builder){
+ this.key = Objects.requireNonNull(builder.key);
+ this.value = builder.value;
+ this.source = Objects.requireNonNull(builder.source);
+ if(builder.metaEntries !=null) {
+ this.metaEntries.putAll(builder.metaEntries);
+ }
+ }
+
+ /**
+ * Creates a new instance
+ * @param key the key, not {@code null}.
+ * @param value the value, not {@code null}.
+ * @param source the source, typically the name of the {@link PropertySource} providing
+ * the value, not {@code null}.
+ */
+ private PropertyValue(String key, String value, String source){
+ this.key = Objects.requireNonNull(key, "Key is required.");
+ this.value = Objects.requireNonNull(value, "Value is required.");
+ this.source = Objects.requireNonNull(source, "Source is required.");
+ }
+
+ /**
+ * The requested key.
+ * @return the, key never {@code null}.
+ */
+ public String getKey() {
+ return key;
+ }
+
+ /**
+ * The source.
+ * @return the source, which provided the value, not {@code null}.
+ * @see PropertySource#getName() .
+ */
+ public String getSource() {
+ return this.source;
+ }
+
+
+ /**
+ * The value.
+ * @return the value, in case a value is null it is valid to return {#code null} as result for
+ * {@link PropertySource#get(String)}.
+ */
+ public String getValue() {
+ return this.value;
+ }
+
+ /**
+ * Creates a full configuration map for this key, value pair and all its meta context data. This map
+ * is also used for subsequent processing, like value filtering.
+ * @return the property value entry map.
+ */
+ public Map<String, String> getMetaEntries() {
+ return Collections.unmodifiableMap(metaEntries);
+ }
+
+ /**
+ * Creates a new builder instance.
+ * @param key the key, not {@code null}.
+ * @param source the source, typically the name of the {@link PropertySource}
+ * providing the value, not {@code null}.
+ * @return a new builder instance.
+ */
+ public static PropertyValueBuilder builder(String key, String source){
+ Objects.requireNonNull(key, "Key must be given.");
+ Objects.requireNonNull(source, "Source must be given");
+
+ return new PropertyValueBuilder(key, source);
+ }
+
+ /**
+ * Creates a new builder instance.
+ * @param key the key, not {@code null}.
+ * @param value the property value, not {@code null}.
+ * @param source the source, typically the name of the {@link PropertySource}
+ * providing the value, not {@code null}.
+ * @return a new builder instance.
+ */
+ public static PropertyValueBuilder builder(String key, String value, String source) {
+ Objects.requireNonNull(key, "Key must be given.");
+ Objects.requireNonNull(value, "Value must be given");
+ Objects.requireNonNull(source, "Source must be given.");
+
+ return new PropertyValueBuilder(key, value, source);
+ }
+
+
+ /**
+ * Creates a new PropertyValue without any metadata..
+ * @param key the key, not {@code null}.
+ * @param value the value.
+ * @param source the source, typically the name of the {@link PropertySource}
+ * providing the value, not {@code null}.
+ * @return a new property value instance, or {@code null},
+ * if the value passed is {@code null}..
+ */
+ public static PropertyValue of(String key, String value, String source) {
+ if (value==null) {
+ return null;
+ }
+ return new PropertyValue(key, value, source);
+ }
+
+ /**
+ * Access the given key from this value. Valid keys are the key or any meta-context key.
+ * @param key the key, not {@code null}.
+ * @return the value found, or {@code null}.
+ */
+ public String getMetaEntry(String key) {
+ return this.metaEntries.get(Objects.requireNonNull(key));
+ }
+
+ /**
+ * Creates a new builder instance based on this item.
+ * @return a new builder, never null.
+ */
+ public PropertyValueBuilder toBuilder() {
+ return new PropertyValueBuilder(this.getKey(), this.getSource())
+ .setValue(this.getValue())
+ .setMetaEntries(this.metaEntries);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof PropertyValue)) return false;
+ PropertyValue that = (PropertyValue) o;
+ return Objects.equals(getKey(), that.getKey()) &&
+ Objects.equals(getValue(), that.getValue()) &&
+ Objects.equals(getSource(), that.getSource()) &&
+ Objects.equals(getMetaEntries(), that.getMetaEntries());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(getKey(), getValue(), getSource(),
+ getMetaEntries());
+ }
+
+ @Override
+ public String toString() {
+ return "PropertyValue{" +
+ "key='" + key + '\'' +
+ ", value='" + value + '\'' +
+ ", source='" + source + '\'' +
+ (metaEntries.isEmpty()?"":", metaEntries=" + metaEntries) +
+ '}';
+ }
+
+ /**
+ * Maps a map of {@code Map<String,String>} to a {@code Map<String,PropertyValue>}.
+ * @param config the String based map, not {@code null}.
+ * @param source the source name, not {@code null}.
+ * @return the corresponding value based map.
+ */
+ public static Map<String,PropertyValue> map(Map<String, String> config, String source) {
+ Map<String,PropertyValue> result = new HashMap<>(config.size());
+ for(Map.Entry<String,String> en:config.entrySet()){
+ result.put(en.getKey(), PropertyValue.of(en.getKey(), en.getValue(), source));
+ }
+ return result;
+ }
+
+ /**
+ * Maps a map of {@code Map<String,String>} to a {@code Map<String,PropertyValue>}.
+ *
+ * @param config the String based map, not {@code null}.
+ * @param source the source name, not {@code null}.
+ * @param metaData additional metadata, not {@code null}.
+ * @return the corresponding value based map.
+ */
+ public static Map<String,PropertyValue> map(Map<String, String> config, String source,
+ Map<String,String> metaData) {
+ Objects.requireNonNull(config, "Config must be given.");
+ Objects.requireNonNull(source, "Source must be given.");
+ Objects.requireNonNull(metaData, "Meta data must be given.");
+
+ Map<String,PropertyValue> result = new HashMap<>(config.size());
+
+ for(Map.Entry<String,String> en:config.entrySet()){
+ PropertyValue value = new PropertyValueBuilder(en.getKey(), source).setValue(en.getValue())
+ .addMetaEntries(metaData).build();
+ result.put(en.getKey(), value);
+ }
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/9bc56a38/code/old/api/src/main/java/org/apache/tamaya/spi/PropertyValueBuilder.java
----------------------------------------------------------------------
diff --git a/code/old/api/src/main/java/org/apache/tamaya/spi/PropertyValueBuilder.java b/code/old/api/src/main/java/org/apache/tamaya/spi/PropertyValueBuilder.java
new file mode 100644
index 0000000..af01987
--- /dev/null
+++ b/code/old/api/src/main/java/org/apache/tamaya/spi/PropertyValueBuilder.java
@@ -0,0 +1,196 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.spi;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * Builder to create a {@link PropertyValue} instance.
+ */
+public class PropertyValueBuilder {
+ /** The key accessed. */
+ String key;
+ /** The property value. */
+ String value;
+ /** The property vaoue source. */
+ String source;
+ /** additional metadata entries (optional). */
+ Map<String,String> metaEntries = new HashMap<>();
+
+ /**
+ * Create a new builder instance, for a given set of parameters.
+ * Before calling build at least a {@link #value} and its {@link #source}
+ * must be set.
+ */
+ PropertyValueBuilder(String key){
+ this.key = Objects.requireNonNull(key);
+ }
+
+ /**
+ * Create a new builder instance, for a given set of parameters.
+ * @param key to access a property value, not {@code null}.
+ * @param source property source.
+ */
+ PropertyValueBuilder(String key, String source) {
+ this.key = Objects.requireNonNull(key);
+ this.source = Objects.requireNonNull(source);
+ }
+
+ /**
+ * Create a new builder instance, for a given set of parameters.
+ *
+ * @param key to access a property value.
+ * @param value the value, not {@code null}. If a value is {@code null}
+ * {@link PropertySource#get(String)} should return {@code null}.
+ * @param source property source.
+ */
+ PropertyValueBuilder(String key, String value, String source) {
+ this.key = Objects.requireNonNull(key);
+ this.value = value;
+ this.source = Objects.requireNonNull(source);
+ }
+
+ /**
+ * Replaces/sets the context data.
+ * @param metaEntries the context data to be applied, not {@code null}.
+ * @return the builder for chaining.
+ */
+ public PropertyValueBuilder setMetaEntries(Map<String, String> metaEntries) {
+ this.metaEntries.clear();
+ this.metaEntries.putAll(metaEntries);
+ return this;
+ }
+
+ /**
+ * Add an additional context data information.
+ * @param key the context data key, not {@code null}.
+ * @param value the context value, not {@code null} (will be converted to String).
+ * @return the builder for chaining.
+ */
+ public PropertyValueBuilder addMetaEntry(String key, Object value) {
+ Objects.requireNonNull(key, "Meta key must be given.");
+ Objects.requireNonNull(value, "Meta value must be given.");
+
+ this.metaEntries.put(key, String.valueOf(value));
+ return this;
+ }
+
+ /**
+ * Adds the context data given.
+ * @param metaEntries the context data to be applied, not {@code null}.
+ * @return the builder for chaining.
+ */
+ public PropertyValueBuilder addMetaEntries(Map<String, String> metaEntries) {
+ this.metaEntries.putAll(metaEntries);
+ return this;
+ }
+
+ /**
+ * Removes a meta entry.
+ * @param key the entry's key, not {@code null}.
+ * @return the builder for chaining.
+ */
+ public PropertyValueBuilder removeMetaEntry(String key) {
+ Objects.requireNonNull(key, "Key must be given.");
+
+ this.metaEntries.remove(key);
+ return this;
+ }
+
+ /**
+ * Get the value's context data.
+ * @return the context data, not {@code null}.
+ */
+ public Map<String,String> getMetaEntries() {
+ return Collections.unmodifiableMap(this.metaEntries);
+ }
+
+ /**
+ * Changes the entry's key, mapping also corresponding context entries.
+ * @param key the new key, not {@code null}.
+ * @return the builder for chaining.
+ */
+ public PropertyValueBuilder mapKey(String key) {
+ // todo obf if (1==1) throw new RuntimeException("No tests written.");
+ Map<String,String> newContext = new HashMap<>();
+ for(Map.Entry<String,String> en:this.metaEntries.entrySet()){
+ if(en.getKey().startsWith("_"+this.key)){
+ newContext.put("_"+key+'.'+ en.getKey().substring(this.key.length()+1), en.getValue());
+ }else{
+ newContext.put(en.getKey(), en.getValue());
+ }
+ }
+ this.metaEntries = newContext;
+ this.key = key;
+ return this;
+ }
+
+ /**
+ * Sets a new key.
+ * @param key the new key, not {@code null}.
+ * @return the builder for chaining.
+ */
+ public PropertyValueBuilder setKey(String key) {
+ this.key = Objects.requireNonNull(key);
+ return this;
+ }
+
+ /**
+ * Sets a new value.
+ * @param value the new value, not {@code null}.
+ * @return the builder for chaining.
+ */
+ public PropertyValueBuilder setValue(String value) {
+ this.value = Objects.requireNonNull(value, "Value must be given.");
+
+ return this;
+ }
+
+ /**
+ * Sets a new source.
+ * @param source the new source, not {@code null}.
+ * @return the builder for chaining.
+ */
+ public PropertyValueBuilder setSource(String source) {
+ // todo obf if (1==1) throw new RuntimeException("No tests written.");
+ this.source = Objects.requireNonNull(source);
+ return this;
+ }
+
+ /**
+ * Creates a new immutable {@link PropertyValue}.
+ * @return a new immutable {@link PropertyValue}, never {@code null}.
+ */
+ public PropertyValue build(){
+ return new PropertyValue(this);
+ }
+
+ @Override
+ public String toString() {
+ return "PropertyValueBuilder{" +
+ "key='" + key + '\'' +
+ "value='" + value + '\'' +
+ ", metaEntries=" + metaEntries +
+ '}';
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/9bc56a38/code/old/api/src/main/java/org/apache/tamaya/spi/PropertyValueCombinationPolicy.java
----------------------------------------------------------------------
diff --git a/code/old/api/src/main/java/org/apache/tamaya/spi/PropertyValueCombinationPolicy.java b/code/old/api/src/main/java/org/apache/tamaya/spi/PropertyValueCombinationPolicy.java
new file mode 100644
index 0000000..14640e6
--- /dev/null
+++ b/code/old/api/src/main/java/org/apache/tamaya/spi/PropertyValueCombinationPolicy.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.spi;
+
+
+/**
+ * Policy that determines how the final value of a configuration entry is evaluated. An instances of this
+ * interface can be registered to get control how multiple PropertySources are combined. This is useful in cases
+ * where the default overriding policy as implemented in {@link #DEFAULT_OVERRIDING_POLICY} is not matching
+ * the need of the current application, e.g. then entries containing multiple values should be combined to new
+ * values instead of overridden.
+ */
+public interface PropertyValueCombinationPolicy {
+
+ /**
+ * Default overriding collector, where each existing entry ({@code current} is overridden by a subsequent non-null
+ * entry evaluated by {@code propertySource.get(key)}.
+ */
+ PropertyValueCombinationPolicy DEFAULT_OVERRIDING_POLICY = new PropertyValueCombinationPolicy(){
+
+ @Override
+ public PropertyValue collect(PropertyValue currentValue, String key, PropertySource propertySource) {
+ PropertyValue value = propertySource.get(key);
+ return value!=null?value:currentValue;
+ }
+ };
+
+ /**
+ * @deprecated Use {@linkplain #DEFAULT_OVERRIDING_POLICY} instead. Will be removed in 1.0.
+ */
+ @Deprecated
+ PropertyValueCombinationPolicy DEFAULT_OVERRIDING_COLLECTOR = DEFAULT_OVERRIDING_POLICY;
+
+
+ /**
+ * Method that is called for each value evaluated by a PropertySource for the given key. This method is called
+ * either when a single key is accessed, e.g. by calling {@code org.apache.tamaya.Configuration.getXXX}, but also
+ * when the full configuration property map is accessed by calling
+ * {@link org.apache.tamaya.Configuration#getProperties()}.
+ *
+ * @param currentValue the current value, including metadata entries. If no such key is present the current value
+ * is null.
+ * The collector should either combine the existing value with value from {@code currentValue}
+ * or replace the value in {@code currentValue} with {@code valueRead}, hereby returning the
+ * result to be used as new {@code currentValue}.
+ * @param key The current key to be evaluated.
+ * @param propertySource The PropertySource that may return an value for the given key. The PropertySource given
+ * may be evaluated for additional meta-data, how the given values are to be combined.
+ * Note that the value returned by a PropertySource can be null. In that case
+ * {@code currentValue} should be returned in almost all cases.
+ * @return the value to be used for future evaluation, including metadata entries.
+ */
+ PropertyValue collect(PropertyValue currentValue, String key, PropertySource propertySource);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/9bc56a38/code/old/api/src/main/java/org/apache/tamaya/spi/ServiceContext.java
----------------------------------------------------------------------
diff --git a/code/old/api/src/main/java/org/apache/tamaya/spi/ServiceContext.java b/code/old/api/src/main/java/org/apache/tamaya/spi/ServiceContext.java
new file mode 100644
index 0000000..9eb18e8
--- /dev/null
+++ b/code/old/api/src/main/java/org/apache/tamaya/spi/ServiceContext.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.spi;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.List;
+
+
+/**
+ * This class models the component that is managing the lifecycle current the
+ * services used by the Configuration API.
+ */
+public interface ServiceContext {
+
+ /**
+ * @return ordinal of the ServiceContext. The one with the highest ordinal will be taken.
+ */
+ int ordinal();
+
+ /**
+ * Access a service singleton via its type.
+ * If multiple implementations for the very serviceType exist then
+ * the one with the highest {@link javax.annotation.Priority} will be used.
+ *
+ * @param <T> the type of the service type.
+ * @param serviceType the service type.
+ * @return The instance to be used, or {@code null}
+ * @throws org.apache.tamaya.ConfigException if there are multiple service implementations with the maximum priority.
+ */
+ <T> T getService(Class<T> serviceType);
+
+ /**
+ * Factory method to create a type, hereby a new instance is created on each access.
+ * If multiple implementations for the very serviceType exist then
+ * the one with the highest {@link javax.annotation.Priority} will be used as the base
+ * for creating subsequent instances.
+ *
+ * @param <T> the type of the service type.
+ * @param serviceType the service type.
+ * @return The new instance to be used, or {@code null}
+ * @throws org.apache.tamaya.ConfigException if there are multiple service implementations with the maximum priority.
+ */
+ <T> T create(Class<T> serviceType);
+
+ /**
+ * Access a list current services, given its type. The bootstrap mechanism should
+ * order the instance for precedence, hereby the most significant should be
+ * first in order.
+ *
+ * @param serviceType
+ * the service type.
+ * @param <T> the type of the list element returned by this method
+ * @return The instance to be used, never {@code null}
+ */
+ <T> List<T> getServices(Class<T> serviceType);
+
+ /**
+ * Loads resources from the current runtime context. This method allows to use runtime
+ * specific code to load resources, e.g. within OSGI environments.
+ * @param resource the resource, not {@code null}.
+ * @param cl the desired classloader context, if null, the current thread context classloader is used.
+ * @return the resources found
+ * @throws IOException if load fails.
+ */
+ Enumeration<URL> getResources(String resource, ClassLoader cl) throws IOException;
+
+ /**
+ * Loads a resource from the current runtime context. This method allows to use runtime
+ * specific code to load a resource, e.g. within OSGI environments.
+ * @param resource the resource, not {@code null}.
+ * @param cl the desired classloader context, if null, the current thread context classloader is used.
+ * @return the resource found, or {@code null}.
+ */
+ URL getResource(String resource, ClassLoader cl);
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/9bc56a38/code/old/api/src/main/java/org/apache/tamaya/spi/ServiceContextManager.java
----------------------------------------------------------------------
diff --git a/code/old/api/src/main/java/org/apache/tamaya/spi/ServiceContextManager.java b/code/old/api/src/main/java/org/apache/tamaya/spi/ServiceContextManager.java
new file mode 100644
index 0000000..f58c27a
--- /dev/null
+++ b/code/old/api/src/main/java/org/apache/tamaya/spi/ServiceContextManager.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.spi;
+
+import java.util.Objects;
+import java.util.ServiceLoader;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.tamaya.ConfigException;
+
+
+/**
+ * This singleton provides access to the services available in the current {@link ServiceContext}. The
+ * behaviour can be adapted, by calling {@link ServiceContextManager#set(ServiceContext)} before accessing any
+ * services.
+ */
+public final class ServiceContextManager {
+
+ /** The logger used. */
+ private static final Logger LOG = Logger.getLogger(ServiceContextManager.class.getName());
+
+ /**
+ * The ServiceProvider used.
+ */
+ private static volatile ServiceContext serviceContextProviderDelegate;
+
+ /**
+ * Private singletons constructor.
+ */
+ private ServiceContextManager() {
+ }
+
+ /**
+ * Load the {@link ServiceContext} to be used.
+ *
+ * @return {@link ServiceContext} to be used for loading the services.
+ */
+ private static ServiceContext loadDefaultServiceProvider() {
+ ServiceContext highestServiceContext = null;
+ try {
+ int highestOrdinal = 0;
+ for (ServiceContext serviceContext : ServiceLoader.load(ServiceContext.class)) {
+ if(highestServiceContext==null){
+ highestServiceContext = serviceContext;
+ }else if (serviceContext.ordinal() > highestOrdinal) {
+ highestServiceContext = serviceContext;
+ highestOrdinal = serviceContext.ordinal();
+ }
+ }
+ } catch (Exception e) {
+ throw new ConfigException("ServiceContext not loadable", e);
+ }
+ if (highestServiceContext==null){
+ throw new ConfigException("No ServiceContext found");
+ }
+ LOG.info("Using Service Context of type: " + highestServiceContext.getClass().getName());
+ return highestServiceContext;
+ }
+
+ /**
+ * Replace the current {@link ServiceContext} in use.
+ *
+ * @param serviceContextProvider the new {@link ServiceContext}, not {@code null}.
+ * @return the currently used context after setting it.
+ */
+ public static ServiceContext set(ServiceContext serviceContextProvider) {
+ Objects.requireNonNull(serviceContextProvider);
+ ServiceContext currentContext = ServiceContextManager.serviceContextProviderDelegate;
+
+ synchronized (ServiceContextManager.class) {
+ if (ServiceContextManager.serviceContextProviderDelegate == null) {
+ ServiceContextManager.serviceContextProviderDelegate = serviceContextProvider;
+ LOG.log(Level.INFO, "Using ServiceProvider: " + serviceContextProvider.getClass().getName());
+ } else {
+ LOG.log(Level.WARNING, "Replacing ServiceProvider " +
+ ServiceContextManager.serviceContextProviderDelegate.getClass().getName() +
+ " with: " + serviceContextProvider.getClass().getName());
+ ServiceContextManager.serviceContextProviderDelegate = serviceContextProvider;
+ }
+ }
+
+ return currentContext;
+ }
+
+ /**
+ * Ge {@link ServiceContext}. If necessary the {@link ServiceContext} will be laziliy loaded.
+ *
+ * @return the {@link ServiceContext} used.
+ */
+ public static ServiceContext getServiceContext() {
+ if (serviceContextProviderDelegate == null) {
+ synchronized (ServiceContextManager.class) {
+ if (serviceContextProviderDelegate == null) {
+ serviceContextProviderDelegate = loadDefaultServiceProvider();
+ }
+ }
+ }
+ return serviceContextProviderDelegate;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/9bc56a38/code/old/api/src/main/java/org/apache/tamaya/spi/package-info.java
----------------------------------------------------------------------
diff --git a/code/old/api/src/main/java/org/apache/tamaya/spi/package-info.java b/code/old/api/src/main/java/org/apache/tamaya/spi/package-info.java
new file mode 100644
index 0000000..49dbab9
--- /dev/null
+++ b/code/old/api/src/main/java/org/apache/tamaya/spi/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * This package contains the Apache Tamaya SPI artifacts.
+ */
+@org.osgi.annotation.versioning.Version("0.4")
+package org.apache.tamaya.spi;
\ No newline at end of file