From 7151304c6fe81593789a07d9f074371c41f3eaaa Mon Sep 17 00:00:00 2001 From: Mark Struberg Date: Wed, 3 Aug 2016 22:59:13 +0200 Subject: [PATCH 01/29] adopt for microprofile --- README.adoc | 7 ++++--- .../{javx => io/microprofile}/config/Config.java | 11 ++++++----- .../microprofile}/config/ConfigProvider.java | 6 +++--- .../microprofile}/config/spi/ConfigFilter.java | 4 ++-- .../microprofile}/config/spi/ConfigSource.java | 2 +- .../config/spi/ConfigSourceProvider.java | 2 +- .../microprofile}/config/spi/Converter.java | 2 +- .../java/org/apache/geronimo/config/ConfigImpl.java | 8 ++++---- .../apache/geronimo/config/DefaultConfigBuilder.java | 10 +++++----- .../geronimo/config/DefaultConfigProvider.java | 4 ++-- .../config/configsource/BaseConfigSource.java | 2 +- .../PropertyFileConfigSourceProvider.java | 4 ++-- .../config/configsource/SystemEnvConfigSource.java | 2 +- .../configsource/SystemPropertyConfigSource.java | 2 +- .../geronimo/config/converters/BooleanConverter.java | 2 +- .../geronimo/config/converters/DoubleConverter.java | 2 +- .../geronimo/config/converters/FloatConverter.java | 2 +- .../geronimo/config/converters/IntegerConverter.java | 2 +- .../geronimo/config/converters/LongConverter.java | 2 +- ...SPI => io.microprofile.config.ConfigProvider$SPI} | 0 spec/pom.xml | 2 +- spec/src/main/asciidoc/architecture.asciidoc | 6 +++--- spec/src/main/asciidoc/configfilters.asciidoc | 2 +- spec/src/main/asciidoc/configsources.asciidoc | 12 ++++++------ spec/src/main/asciidoc/converters.asciidoc | 8 +++++--- ...ec.asciidoc => microprofile-config-spec.asciidoc} | 2 +- .../apache/geronimo/config/tck/ConfigFilterTest.java | 4 ++-- .../geronimo/config/tck/ConfigProviderTest.java | 4 ++-- .../config/tck/ConfigSourceProviderTest.java | 4 ++-- .../apache/geronimo/config/tck/ConverterTest.java | 4 ++-- .../geronimo/config/tck/CustomConfigSourceTest.java | 4 ++-- .../tck/configfilters/PasswordConfigFilter.java | 2 +- .../configsources/CustomConfigSourceProvider.java | 4 ++-- .../tck/configsources/CustomDbConfigSource.java | 2 +- .../tck/configsources/SampleYamlConfigSource.java | 2 +- .../config/tck/converters/DuckConverter.java | 2 +- ...ilter => io.microprofile.config.spi.ConfigFilter} | 0 ...ource => io.microprofile.config.spi.ConfigSource} | 0 ... io.microprofile.config.spi.ConfigSourceProvider} | 0 39 files changed, 72 insertions(+), 68 deletions(-) rename api/src/main/java/{javx => io/microprofile}/config/Config.java (92%) rename api/src/main/java/{javx => io/microprofile}/config/ConfigProvider.java (97%) rename api/src/main/java/{javx => io/microprofile}/config/spi/ConfigFilter.java (96%) rename api/src/main/java/{javx => io/microprofile}/config/spi/ConfigSource.java (99%) rename api/src/main/java/{javx => io/microprofile}/config/spi/ConfigSourceProvider.java (98%) rename api/src/main/java/{javx => io/microprofile}/config/spi/Converter.java (98%) rename impl/src/main/resources/META-INF/services/{javx.config.ConfigProvider$SPI => io.microprofile.config.ConfigProvider$SPI} (100%) rename spec/src/main/asciidoc/{javaconfig-spec.asciidoc => microprofile-config-spec.asciidoc} (97%) rename tck/src/main/resources/META-INF/services/{javx.config.spi.ConfigFilter => io.microprofile.config.spi.ConfigFilter} (100%) rename tck/src/main/resources/META-INF/services/{javx.config.spi.ConfigSource => io.microprofile.config.spi.ConfigSource} (100%) rename tck/src/main/resources/META-INF/services/{javx.config.spi.ConfigSourceProvider => io.microprofile.config.spi.ConfigSourceProvider} (100%) diff --git a/README.adoc b/README.adoc index 7d48664..63fb9be 100644 --- a/README.adoc +++ b/README.adoc @@ -15,11 +15,11 @@ // limitations under the License. // -# Configuration for Java SE and EE JSR +# Configuration for Java SE and EE ## Status -JSR proposal! +Microprofile proposal! == Rational @@ -35,6 +35,7 @@ But be able to overwrite those default values from external. This very configuration approach has it's roots in the Apache OpenWebBeans internal SPI configuration. In 2010 it got moved over to the Apache MyFaces CODI project and enhanced to also fit the need of customer projects by Gerhard Petracek and Mark Struberg. In 2012 we further enhanced it while moving CODI to the Apache DeltaSpike project. +Romain Manni-Bucau (Apache/Tomitribe), Ron Smeral (JBoss) and Anatole Tresch also gave appreciated input in the last years. == How it works @@ -60,4 +61,4 @@ An example would be a ConfigSource which gets the configured values from a share `$> mvn clean install` -After that the specification PDF can be found in `spec/target/generated-docs/config-spec.pdf` \ No newline at end of file +After that the specification PDF can be found in `spec/target/generated-docs/microprofile-config-spec.pdf` \ No newline at end of file diff --git a/api/src/main/java/javx/config/Config.java b/api/src/main/java/io/microprofile/config/Config.java similarity index 92% rename from api/src/main/java/javx/config/Config.java rename to api/src/main/java/io/microprofile/config/Config.java index 0f4380e..f7b0b1f 100644 --- a/api/src/main/java/javx/config/Config.java +++ b/api/src/main/java/io/microprofile/config/Config.java @@ -14,12 +14,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package javx.config; +package io.microprofile.config; import java.util.Map; -import javx.config.spi.ConfigSource; -import javx.config.spi.ConfigSourceProvider; +import io.microprofile.config.spi.ConfigSourceProvider; +import io.microprofile.config.spi.Converter; +import io.microprofile.config.spi.ConfigSource; /** *

Resolves configured values of properties by going through the list @@ -53,14 +54,14 @@ public interface Config { * @param asType Also support parameterized Types? * @param * @return - * @throws UnsupportedOperationException if there is no {@link javx.config.spi.Converter} registered for asType + * @throws UnsupportedOperationException if there is no {@link Converter} registered for asType */ T getValue(String key, Class asType); /** * Apply the * @return the String converted - * @throws UnsupportedOperationException if there is no {@link javx.config.spi.Converter} registered for asType + * @throws UnsupportedOperationException if there is no {@link Converter} registered for asType */ T convert(String value, Class asType); diff --git a/api/src/main/java/javx/config/ConfigProvider.java b/api/src/main/java/io/microprofile/config/ConfigProvider.java similarity index 97% rename from api/src/main/java/javx/config/ConfigProvider.java rename to api/src/main/java/io/microprofile/config/ConfigProvider.java index b3caf0c..d693a06 100644 --- a/api/src/main/java/javx/config/ConfigProvider.java +++ b/api/src/main/java/io/microprofile/config/ConfigProvider.java @@ -14,13 +14,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package javx.config; +package io.microprofile.config; import java.util.ServiceLoader; import java.util.logging.Logger; -import javx.config.spi.ConfigFilter; -import javx.config.spi.ConfigSource; +import io.microprofile.config.spi.ConfigFilter; +import io.microprofile.config.spi.ConfigSource; /** *

This is the central class to access a {@link Config}.

diff --git a/api/src/main/java/javx/config/spi/ConfigFilter.java b/api/src/main/java/io/microprofile/config/spi/ConfigFilter.java similarity index 96% rename from api/src/main/java/javx/config/spi/ConfigFilter.java rename to api/src/main/java/io/microprofile/config/spi/ConfigFilter.java index 0e01b51..f327778 100644 --- a/api/src/main/java/javx/config/spi/ConfigFilter.java +++ b/api/src/main/java/io/microprofile/config/spi/ConfigFilter.java @@ -16,9 +16,9 @@ * specific language governing permissions and limitations * under the License. */ -package javx.config.spi; +package io.microprofile.config.spi; -import javx.config.Config; +import io.microprofile.config.Config; /** *

A filter which can be added to the diff --git a/api/src/main/java/javx/config/spi/ConfigSource.java b/api/src/main/java/io/microprofile/config/spi/ConfigSource.java similarity index 99% rename from api/src/main/java/javx/config/spi/ConfigSource.java rename to api/src/main/java/io/microprofile/config/spi/ConfigSource.java index f66f552..5b0f06b 100644 --- a/api/src/main/java/javx/config/spi/ConfigSource.java +++ b/api/src/main/java/io/microprofile/config/spi/ConfigSource.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package javx.config.spi; +package io.microprofile.config.spi; import java.util.Map; diff --git a/api/src/main/java/javx/config/spi/ConfigSourceProvider.java b/api/src/main/java/io/microprofile/config/spi/ConfigSourceProvider.java similarity index 98% rename from api/src/main/java/javx/config/spi/ConfigSourceProvider.java rename to api/src/main/java/io/microprofile/config/spi/ConfigSourceProvider.java index b3f3a46..8b9b4f8 100644 --- a/api/src/main/java/javx/config/spi/ConfigSourceProvider.java +++ b/api/src/main/java/io/microprofile/config/spi/ConfigSourceProvider.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package javx.config.spi; +package io.microprofile.config.spi; import java.util.List; diff --git a/api/src/main/java/javx/config/spi/Converter.java b/api/src/main/java/io/microprofile/config/spi/Converter.java similarity index 98% rename from api/src/main/java/javx/config/spi/Converter.java rename to api/src/main/java/io/microprofile/config/spi/Converter.java index 07a86a5..0d655d6 100644 --- a/api/src/main/java/javx/config/spi/Converter.java +++ b/api/src/main/java/io/microprofile/config/spi/Converter.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package javx.config.spi; +package io.microprofile.config.spi; /** *

A very simple interface for conversion of configuration values from String to any Java type.

diff --git a/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java b/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java index 44eb254..6aa702c 100644 --- a/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java +++ b/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java @@ -28,10 +28,10 @@ import java.util.logging.Level; import java.util.logging.Logger; -import javx.config.Config; -import javx.config.spi.ConfigFilter; -import javx.config.spi.ConfigSource; -import javx.config.spi.Converter; +import io.microprofile.config.Config; +import io.microprofile.config.spi.ConfigFilter; +import io.microprofile.config.spi.ConfigSource; +import io.microprofile.config.spi.Converter; import org.apache.geronimo.config.converters.BooleanConverter; import org.apache.geronimo.config.converters.DoubleConverter; import org.apache.geronimo.config.converters.FloatConverter; diff --git a/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java b/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java index e70c59b..bd9afa2 100644 --- a/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java +++ b/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java @@ -16,11 +16,11 @@ */ package org.apache.geronimo.config; -import javx.config.Config; -import javx.config.ConfigProvider; -import javx.config.spi.ConfigFilter; -import javx.config.spi.ConfigSource; -import javx.config.spi.ConfigSourceProvider; +import io.microprofile.config.Config; +import io.microprofile.config.ConfigProvider; +import io.microprofile.config.spi.ConfigFilter; +import io.microprofile.config.spi.ConfigSource; +import io.microprofile.config.spi.ConfigSourceProvider; import org.apache.geronimo.config.configsource.PropertyFileConfigSourceProvider; import org.apache.geronimo.config.configsource.SystemEnvConfigSource; import org.apache.geronimo.config.configsource.SystemPropertyConfigSource; diff --git a/impl/src/main/java/org/apache/geronimo/config/DefaultConfigProvider.java b/impl/src/main/java/org/apache/geronimo/config/DefaultConfigProvider.java index 388624e..07605f9 100644 --- a/impl/src/main/java/org/apache/geronimo/config/DefaultConfigProvider.java +++ b/impl/src/main/java/org/apache/geronimo/config/DefaultConfigProvider.java @@ -21,8 +21,8 @@ import java.util.Iterator; import java.util.Map; import java.util.WeakHashMap; -import javx.config.Config; -import javx.config.ConfigProvider; +import io.microprofile.config.Config; +import io.microprofile.config.ConfigProvider; /** diff --git a/impl/src/main/java/org/apache/geronimo/config/configsource/BaseConfigSource.java b/impl/src/main/java/org/apache/geronimo/config/configsource/BaseConfigSource.java index 1f41c5f..9ffbc10 100644 --- a/impl/src/main/java/org/apache/geronimo/config/configsource/BaseConfigSource.java +++ b/impl/src/main/java/org/apache/geronimo/config/configsource/BaseConfigSource.java @@ -21,7 +21,7 @@ import java.util.logging.Level; import java.util.logging.Logger; -import javx.config.spi.ConfigSource; +import io.microprofile.config.spi.ConfigSource; /** diff --git a/impl/src/main/java/org/apache/geronimo/config/configsource/PropertyFileConfigSourceProvider.java b/impl/src/main/java/org/apache/geronimo/config/configsource/PropertyFileConfigSourceProvider.java index 9d6e218..6404f92 100644 --- a/impl/src/main/java/org/apache/geronimo/config/configsource/PropertyFileConfigSourceProvider.java +++ b/impl/src/main/java/org/apache/geronimo/config/configsource/PropertyFileConfigSourceProvider.java @@ -26,8 +26,8 @@ import java.util.logging.Level; import java.util.logging.Logger; -import javx.config.spi.ConfigSource; -import javx.config.spi.ConfigSourceProvider; +import io.microprofile.config.spi.ConfigSource; +import io.microprofile.config.spi.ConfigSourceProvider; /** diff --git a/impl/src/main/java/org/apache/geronimo/config/configsource/SystemEnvConfigSource.java b/impl/src/main/java/org/apache/geronimo/config/configsource/SystemEnvConfigSource.java index c45a47d..bf5e171 100644 --- a/impl/src/main/java/org/apache/geronimo/config/configsource/SystemEnvConfigSource.java +++ b/impl/src/main/java/org/apache/geronimo/config/configsource/SystemEnvConfigSource.java @@ -21,7 +21,7 @@ import java.util.Map; -import javx.config.spi.ConfigSource; +import io.microprofile.config.spi.ConfigSource; /** * {@link ConfigSource} which uses {@link System#getenv()} diff --git a/impl/src/main/java/org/apache/geronimo/config/configsource/SystemPropertyConfigSource.java b/impl/src/main/java/org/apache/geronimo/config/configsource/SystemPropertyConfigSource.java index f29cf23..73ce7f1 100644 --- a/impl/src/main/java/org/apache/geronimo/config/configsource/SystemPropertyConfigSource.java +++ b/impl/src/main/java/org/apache/geronimo/config/configsource/SystemPropertyConfigSource.java @@ -20,7 +20,7 @@ import java.util.Map; -import javx.config.spi.ConfigSource; +import io.microprofile.config.spi.ConfigSource; /** * {@link ConfigSource} which uses {@link System#getProperties()} diff --git a/impl/src/main/java/org/apache/geronimo/config/converters/BooleanConverter.java b/impl/src/main/java/org/apache/geronimo/config/converters/BooleanConverter.java index 5df76ee..72e03b4 100644 --- a/impl/src/main/java/org/apache/geronimo/config/converters/BooleanConverter.java +++ b/impl/src/main/java/org/apache/geronimo/config/converters/BooleanConverter.java @@ -16,7 +16,7 @@ */ package org.apache.geronimo.config.converters; -import javx.config.spi.Converter; +import io.microprofile.config.spi.Converter; import javax.annotation.Priority; diff --git a/impl/src/main/java/org/apache/geronimo/config/converters/DoubleConverter.java b/impl/src/main/java/org/apache/geronimo/config/converters/DoubleConverter.java index 99b0add..c32860f 100644 --- a/impl/src/main/java/org/apache/geronimo/config/converters/DoubleConverter.java +++ b/impl/src/main/java/org/apache/geronimo/config/converters/DoubleConverter.java @@ -16,7 +16,7 @@ */ package org.apache.geronimo.config.converters; -import javx.config.spi.Converter; +import io.microprofile.config.spi.Converter; import javax.annotation.Priority; diff --git a/impl/src/main/java/org/apache/geronimo/config/converters/FloatConverter.java b/impl/src/main/java/org/apache/geronimo/config/converters/FloatConverter.java index c8d5806..fa7372a 100644 --- a/impl/src/main/java/org/apache/geronimo/config/converters/FloatConverter.java +++ b/impl/src/main/java/org/apache/geronimo/config/converters/FloatConverter.java @@ -18,7 +18,7 @@ import javax.annotation.Priority; -import javx.config.spi.Converter; +import io.microprofile.config.spi.Converter; /** * @author Mark Struberg diff --git a/impl/src/main/java/org/apache/geronimo/config/converters/IntegerConverter.java b/impl/src/main/java/org/apache/geronimo/config/converters/IntegerConverter.java index e3c7e0d..cb76c63 100644 --- a/impl/src/main/java/org/apache/geronimo/config/converters/IntegerConverter.java +++ b/impl/src/main/java/org/apache/geronimo/config/converters/IntegerConverter.java @@ -18,7 +18,7 @@ import javax.annotation.Priority; -import javx.config.spi.Converter; +import io.microprofile.config.spi.Converter; /** * @author Mark Struberg diff --git a/impl/src/main/java/org/apache/geronimo/config/converters/LongConverter.java b/impl/src/main/java/org/apache/geronimo/config/converters/LongConverter.java index 2d9eff6..4df6eaa 100644 --- a/impl/src/main/java/org/apache/geronimo/config/converters/LongConverter.java +++ b/impl/src/main/java/org/apache/geronimo/config/converters/LongConverter.java @@ -16,7 +16,7 @@ */ package org.apache.geronimo.config.converters; -import javx.config.spi.Converter; +import io.microprofile.config.spi.Converter; import javax.annotation.Priority; diff --git a/impl/src/main/resources/META-INF/services/javx.config.ConfigProvider$SPI b/impl/src/main/resources/META-INF/services/io.microprofile.config.ConfigProvider$SPI similarity index 100% rename from impl/src/main/resources/META-INF/services/javx.config.ConfigProvider$SPI rename to impl/src/main/resources/META-INF/services/io.microprofile.config.ConfigProvider$SPI diff --git a/spec/pom.xml b/spec/pom.xml index 756115a..416f9c5 100644 --- a/spec/pom.xml +++ b/spec/pom.xml @@ -77,7 +77,7 @@ - javaconfig-spec.asciidoc + microprofile-config-spec.asciidoc coderay Apache License v2.0 diff --git a/spec/src/main/asciidoc/architecture.asciidoc b/spec/src/main/asciidoc/architecture.asciidoc index e73dd3d..11af860 100644 --- a/spec/src/main/asciidoc/architecture.asciidoc +++ b/spec/src/main/asciidoc/architecture.asciidoc @@ -28,10 +28,10 @@ This might be different REST endpoints to talk with (e.g. depending on the custo Or it might even be different features which need to be switched on and off depending on the installation. All this must be possible without the need to re-package the whole application binary. -Java-config provides a way to achieve this goal by aggregating configuration from many different sources and presents a single merged view to the user. +Microprofile-Config provides a way to achieve this goal by aggregating configuration from many different sources and presents a single merged view to the user. This allows the application to bundle default configuration within the application. It also allows to override the defaults from outside, e.g. via an environment variable a Java system property or via Docker. -Java-config also allows to implement and register own configuration sources in a portable way, e.g. for reading configuration values from a shared database in an application cluster. +Microprofile-Config also allows to implement and register own configuration sources in a portable way, e.g. for reading configuration values from a shared database in an application cluster. === Accessing a certain Configuration @@ -63,7 +63,7 @@ Any subsequent call to `ConfigProvider#getConfig()` or `ConfigProvider#getConfig === Configuration Lookup Mechanism Example -The core Java-config mechanism is purely String/String based. +The core Microprofile-Config mechanism is purely String/String based. Type-safety is only provided on top of that by using the proper `Converter` before handing the value out to the caller. The configuration key might use dot-separated namespaces similar to Java package namespacing: diff --git a/spec/src/main/asciidoc/configfilters.asciidoc b/spec/src/main/asciidoc/configfilters.asciidoc index 631f618..b32eb96 100644 --- a/spec/src/main/asciidoc/configfilters.asciidoc +++ b/spec/src/main/asciidoc/configfilters.asciidoc @@ -22,7 +22,7 @@ A `ConfigFilter` acts as a valve which is able to modify the configured values b An implementation of the specification is not required to ship with any `ConfigFilters` enabled by default. -A custom `ConfigFilter` must implement the interface `javx.config.spi.ConfigFilter` and is typically registered in a classpath resource `/META-INF/services/javx.config.spi.ConfigFilter` by including the fully-qualified class name of the custom implementation (well-known Java SE `java.util.ServiceLoader` mechanism). +A custom `ConfigFilter` must implement the interface `io.microprofile.config.spi.ConfigFilter` and is typically registered in a classpath resource `/META-INF/services/io.microprofile.config.spi.ConfigFilter` by including the fully-qualified class name of the custom implementation (well-known Java SE `java.util.ServiceLoader` mechanism). Alternatively a user can register a `ConfigFilter` manually via `void Config#addConfigFilter(ConfigFilter configFilterToAdd)`. diff --git a/spec/src/main/asciidoc/configsources.asciidoc b/spec/src/main/asciidoc/configsources.asciidoc index f4f008e..74b9dd8 100644 --- a/spec/src/main/asciidoc/configsources.asciidoc +++ b/spec/src/main/asciidoc/configsources.asciidoc @@ -41,7 +41,7 @@ com.acme.myproject.someserver.url = http://more_important.server/some/endpoint === Default ConfigSources -A Java-config implementation must provide `ConfigSource` s for the following data out of the box: +A Microprofile-Config implementation must provide `ConfigSource` s for the following data out of the box: * System properties (ordinal=400) * Environment properties (ordinal=300) @@ -51,7 +51,7 @@ A Java-config implementation must provide `ConfigSource` s for the following dat `ConfigSource` s are discovered using the `java.util.ServiceLoader` mechanism. -To add a custom `ConfigSource`, implement the interface `javx.config.spi.ConfigSource`. +To add a custom `ConfigSource`, implement the interface `io.microprofile.config.spi.ConfigSource`. [source, java] ---- @@ -82,7 +82,7 @@ public class CustomDbConfigSource implements ConfigSource { ---- -Then register your implementation in a resource file `/META-INF/services/javx.config.spi.ConfigSource` by including the fully-qualified class name of the custom implementation in the file. +Then register your implementation in a resource file `/META-INF/services/io.microprofile.config.spi.ConfigSource` by including the fully-qualified class name of the custom implementation in the file. === Custom ConfigSources via ConfigSourceProvider @@ -91,15 +91,15 @@ If you need dynamic `ConfigSource` s you can also register a `ConfigSourceProvid This is useful if you are required to dynamically pick up multiple `ConfigSource` s of the same kind; for example, to pick up all `myproject.properties` resources from all the JARs in your classpath. -A custom `ConfigSourceProvider` must implement the interface `javx.config.spi.ConfigSourceProvider`. -Register your implementation in a resource file `/META-INF/services/javx.config.spi.ConfigSourceProvider` by including the fully-qualified class name of the custom implementation/s in the file. +A custom `ConfigSourceProvider` must implement the interface `io.microprofile.config.spi.ConfigSourceProvider`. +Register your implementation in a resource file `/META-INF/services/io.microprofile.config.spi.ConfigSourceProvider` by including the fully-qualified class name of the custom implementation/s in the file. An example which registers all YAML files with the name `exampleconfig.yaml`: [source, java] ---- public class ExampleYamlConfigSourceProvider - implements javx.config.spi.ConfigSourceProvider { + implements io.microprofile.config.spi.ConfigSourceProvider { @Override public List getConfigSources(ClassLoader forClassLoader) { List configSources = new ArrayList<>(); diff --git a/spec/src/main/asciidoc/converters.asciidoc b/spec/src/main/asciidoc/converters.asciidoc index e8e1010..589891b 100644 --- a/spec/src/main/asciidoc/converters.asciidoc +++ b/spec/src/main/asciidoc/converters.asciidoc @@ -23,7 +23,7 @@ This happens by providing `Converter` s in the `Config`. === Built-in Converters -The following `Converter` s are provided by Java-config by default: +The following `Converter` s are provided by Microprofile-Config by default: * `Boolean` , values for `true` (case insensitive) "true", "1", "YES", "Y" "JA" "J", "OUI". Any other value will be interpreted as `false` @@ -31,13 +31,15 @@ The following `Converter` s are provided by Java-config by default: * `Long` * `Float` , a dot '.' is used to separate the fractional digits * `Double` , a dot '.' is used to separate the fractional digits +* `java.util.Date` in ISO-8601 format (https://www.ietf.org/rfc/rfc3339.txt), e.g. YYYY-MM-DD. Remaining fractions are set to 0. +* Java8 `LocalDate` and `LocalDateTime`in ISO-8601 format === Adding custom Converters -A custom `Converter` must implement the generic interface `javx.config.spi.Converter`. +A custom `Converter` must implement the generic interface `io.microprofile.config.spi.Converter`. The TypedParameter of the interface is the target type the String is converted to -You have to register your implementation in a file `/META-INF/services/javx.config.spi.Converter` by writing the fully qualified class name of the custom implementation into it. +You have to register your implementation in a file `/META-INF/services/io.microprofile.config.spi.Converter` by writing the fully qualified class name of the custom implementation into it. A custom `Converter` can define a priority with the `@javax.annotation.Priority` annotation. If a Priority annotation isn't applied, a default priority of 100 is assumed. diff --git a/spec/src/main/asciidoc/javaconfig-spec.asciidoc b/spec/src/main/asciidoc/microprofile-config-spec.asciidoc similarity index 97% rename from spec/src/main/asciidoc/javaconfig-spec.asciidoc rename to spec/src/main/asciidoc/microprofile-config-spec.asciidoc index e2cb17a..92686df 100644 --- a/spec/src/main/asciidoc/javaconfig-spec.asciidoc +++ b/spec/src/main/asciidoc/microprofile-config-spec.asciidoc @@ -15,7 +15,7 @@ // limitations under the License. // -= JSR XXX: Configuration for Java += Configuration for Microprofile :author: Mark Struberg :email: struberg@apache.org :revnumber: 0.1 diff --git a/tck/src/main/java/org/apache/geronimo/config/tck/ConfigFilterTest.java b/tck/src/main/java/org/apache/geronimo/config/tck/ConfigFilterTest.java index 1c826b2..683b3a7 100644 --- a/tck/src/main/java/org/apache/geronimo/config/tck/ConfigFilterTest.java +++ b/tck/src/main/java/org/apache/geronimo/config/tck/ConfigFilterTest.java @@ -16,8 +16,8 @@ */ package org.apache.geronimo.config.tck; -import javx.config.Config; -import javx.config.ConfigProvider; +import io.microprofile.config.Config; +import io.microprofile.config.ConfigProvider; import org.testng.Assert; import org.testng.annotations.Test; diff --git a/tck/src/main/java/org/apache/geronimo/config/tck/ConfigProviderTest.java b/tck/src/main/java/org/apache/geronimo/config/tck/ConfigProviderTest.java index ec99dfe..aafa3f5 100644 --- a/tck/src/main/java/org/apache/geronimo/config/tck/ConfigProviderTest.java +++ b/tck/src/main/java/org/apache/geronimo/config/tck/ConfigProviderTest.java @@ -21,8 +21,8 @@ import java.util.Map; import java.util.Properties; -import javx.config.Config; -import javx.config.ConfigProvider; +import io.microprofile.config.Config; +import io.microprofile.config.ConfigProvider; import org.testng.Assert; import org.testng.annotations.Test; diff --git a/tck/src/main/java/org/apache/geronimo/config/tck/ConfigSourceProviderTest.java b/tck/src/main/java/org/apache/geronimo/config/tck/ConfigSourceProviderTest.java index f95dca2..664d27d 100644 --- a/tck/src/main/java/org/apache/geronimo/config/tck/ConfigSourceProviderTest.java +++ b/tck/src/main/java/org/apache/geronimo/config/tck/ConfigSourceProviderTest.java @@ -16,8 +16,8 @@ */ package org.apache.geronimo.config.tck; -import javx.config.Config; -import javx.config.ConfigProvider; +import io.microprofile.config.Config; +import io.microprofile.config.ConfigProvider; import org.testng.Assert; import org.testng.annotations.Test; diff --git a/tck/src/main/java/org/apache/geronimo/config/tck/ConverterTest.java b/tck/src/main/java/org/apache/geronimo/config/tck/ConverterTest.java index da3558f..dfa8e0b 100644 --- a/tck/src/main/java/org/apache/geronimo/config/tck/ConverterTest.java +++ b/tck/src/main/java/org/apache/geronimo/config/tck/ConverterTest.java @@ -16,8 +16,8 @@ */ package org.apache.geronimo.config.tck; -import javx.config.Config; -import javx.config.ConfigProvider; +import io.microprofile.config.Config; +import io.microprofile.config.ConfigProvider; import org.testng.Assert; import org.testng.annotations.Test; diff --git a/tck/src/main/java/org/apache/geronimo/config/tck/CustomConfigSourceTest.java b/tck/src/main/java/org/apache/geronimo/config/tck/CustomConfigSourceTest.java index 99e89a6..83b0758 100644 --- a/tck/src/main/java/org/apache/geronimo/config/tck/CustomConfigSourceTest.java +++ b/tck/src/main/java/org/apache/geronimo/config/tck/CustomConfigSourceTest.java @@ -16,8 +16,8 @@ */ package org.apache.geronimo.config.tck; -import javx.config.Config; -import javx.config.ConfigProvider; +import io.microprofile.config.Config; +import io.microprofile.config.ConfigProvider; import org.testng.Assert; import org.testng.annotations.Test; diff --git a/tck/src/main/java/org/apache/geronimo/config/tck/configfilters/PasswordConfigFilter.java b/tck/src/main/java/org/apache/geronimo/config/tck/configfilters/PasswordConfigFilter.java index 1d472e8..4186b86 100644 --- a/tck/src/main/java/org/apache/geronimo/config/tck/configfilters/PasswordConfigFilter.java +++ b/tck/src/main/java/org/apache/geronimo/config/tck/configfilters/PasswordConfigFilter.java @@ -16,7 +16,7 @@ */ package org.apache.geronimo.config.tck.configfilters; -import javx.config.spi.ConfigFilter; +import io.microprofile.config.spi.ConfigFilter; /** * @author Mark Struberg diff --git a/tck/src/main/java/org/apache/geronimo/config/tck/configsources/CustomConfigSourceProvider.java b/tck/src/main/java/org/apache/geronimo/config/tck/configsources/CustomConfigSourceProvider.java index d14bbb9..33691d0 100644 --- a/tck/src/main/java/org/apache/geronimo/config/tck/configsources/CustomConfigSourceProvider.java +++ b/tck/src/main/java/org/apache/geronimo/config/tck/configsources/CustomConfigSourceProvider.java @@ -22,8 +22,8 @@ import java.util.Enumeration; import java.util.List; -import javx.config.spi.ConfigSource; -import javx.config.spi.ConfigSourceProvider; +import io.microprofile.config.spi.ConfigSource; +import io.microprofile.config.spi.ConfigSourceProvider; /** * @author Mark Struberg diff --git a/tck/src/main/java/org/apache/geronimo/config/tck/configsources/CustomDbConfigSource.java b/tck/src/main/java/org/apache/geronimo/config/tck/configsources/CustomDbConfigSource.java index c9ebfdf..a5741d5 100644 --- a/tck/src/main/java/org/apache/geronimo/config/tck/configsources/CustomDbConfigSource.java +++ b/tck/src/main/java/org/apache/geronimo/config/tck/configsources/CustomDbConfigSource.java @@ -19,7 +19,7 @@ import java.util.HashMap; import java.util.Map; -import javx.config.spi.ConfigSource; +import io.microprofile.config.spi.ConfigSource; /** * @author Mark Struberg diff --git a/tck/src/main/java/org/apache/geronimo/config/tck/configsources/SampleYamlConfigSource.java b/tck/src/main/java/org/apache/geronimo/config/tck/configsources/SampleYamlConfigSource.java index 896a668..2ea346b 100644 --- a/tck/src/main/java/org/apache/geronimo/config/tck/configsources/SampleYamlConfigSource.java +++ b/tck/src/main/java/org/apache/geronimo/config/tck/configsources/SampleYamlConfigSource.java @@ -20,7 +20,7 @@ import java.util.HashMap; import java.util.Map; -import javx.config.spi.ConfigSource; +import io.microprofile.config.spi.ConfigSource; /** * @author Mark Struberg diff --git a/tck/src/main/java/org/apache/geronimo/config/tck/converters/DuckConverter.java b/tck/src/main/java/org/apache/geronimo/config/tck/converters/DuckConverter.java index f8337bd..fe51b8d 100644 --- a/tck/src/main/java/org/apache/geronimo/config/tck/converters/DuckConverter.java +++ b/tck/src/main/java/org/apache/geronimo/config/tck/converters/DuckConverter.java @@ -16,7 +16,7 @@ */ package org.apache.geronimo.config.tck.converters; -import javx.config.spi.Converter; +import io.microprofile.config.spi.Converter; /** * @author Mark Struberg diff --git a/tck/src/main/resources/META-INF/services/javx.config.spi.ConfigFilter b/tck/src/main/resources/META-INF/services/io.microprofile.config.spi.ConfigFilter similarity index 100% rename from tck/src/main/resources/META-INF/services/javx.config.spi.ConfigFilter rename to tck/src/main/resources/META-INF/services/io.microprofile.config.spi.ConfigFilter diff --git a/tck/src/main/resources/META-INF/services/javx.config.spi.ConfigSource b/tck/src/main/resources/META-INF/services/io.microprofile.config.spi.ConfigSource similarity index 100% rename from tck/src/main/resources/META-INF/services/javx.config.spi.ConfigSource rename to tck/src/main/resources/META-INF/services/io.microprofile.config.spi.ConfigSource diff --git a/tck/src/main/resources/META-INF/services/javx.config.spi.ConfigSourceProvider b/tck/src/main/resources/META-INF/services/io.microprofile.config.spi.ConfigSourceProvider similarity index 100% rename from tck/src/main/resources/META-INF/services/javx.config.spi.ConfigSourceProvider rename to tck/src/main/resources/META-INF/services/io.microprofile.config.spi.ConfigSourceProvider From 6ae692627723c44d9bdb36b5371d2dacb428c6ae Mon Sep 17 00:00:00 2001 From: Mark Struberg Date: Fri, 5 Aug 2016 09:34:25 +0200 Subject: [PATCH 02/29] fix licensing header for the spec docs --- spec/src/main/asciidoc/configsources.asciidoc | 4 ++-- spec/src/main/asciidoc/license-alv2.asciidoc | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/spec/src/main/asciidoc/configsources.asciidoc b/spec/src/main/asciidoc/configsources.asciidoc index 74b9dd8..beeb73e 100644 --- a/spec/src/main/asciidoc/configsources.asciidoc +++ b/spec/src/main/asciidoc/configsources.asciidoc @@ -104,8 +104,8 @@ public class ExampleYamlConfigSourceProvider public List getConfigSources(ClassLoader forClassLoader) { List configSources = new ArrayList<>(); - Enumeration yamlFiles = null; - yamlFiles = forClassLoader.getResources("sampleconfig.yaml"); + Enumeration yamlFiles + = forClassLoader.getResources("sampleconfig.yaml"); while (yamlFiles.hasMoreElements()) { configSources.add(new SampleYamlConfigSource(yamlFiles.nextElement())); } diff --git a/spec/src/main/asciidoc/license-alv2.asciidoc b/spec/src/main/asciidoc/license-alv2.asciidoc index 9876e47..ddbfded 100644 --- a/spec/src/main/asciidoc/license-alv2.asciidoc +++ b/spec/src/main/asciidoc/license-alv2.asciidoc @@ -28,7 +28,10 @@ Specification Lead: Mark Struberg Release: {revdate} -Copyright 2016 Apache Software Foundation +Copyright 2016 Original Authors, +Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. +Licensed to the Microprofile.io community. + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From a066efe1a587a92086220992ac226dd864f6d435 Mon Sep 17 00:00:00 2001 From: Mark Struberg Date: Sun, 17 Jul 2016 13:11:11 +0200 Subject: [PATCH 03/29] add an access layer on top of the minimal configuration API --- .../java/io/microprofile/config/Config.java | 7 + .../io/microprofile/config/ConfigValue.java | 130 +++++++++++ .../apache/geronimo/config/ConfigImpl.java | 5 + .../geronimo/config/ConfigValueImpl.java | 219 ++++++++++++++++++ .../config/DefaultConfigProvider.java | 5 +- .../geronimo/config/tck/ConfigValueTest.java | 132 +++++++++++ 6 files changed, 496 insertions(+), 2 deletions(-) create mode 100644 api/src/main/java/io/microprofile/config/ConfigValue.java create mode 100644 impl/src/main/java/org/apache/geronimo/config/ConfigValueImpl.java create mode 100644 tck/src/main/java/org/apache/geronimo/config/tck/ConfigValueTest.java diff --git a/api/src/main/java/io/microprofile/config/Config.java b/api/src/main/java/io/microprofile/config/Config.java index f7b0b1f..332f670 100644 --- a/api/src/main/java/io/microprofile/config/Config.java +++ b/api/src/main/java/io/microprofile/config/Config.java @@ -37,6 +37,13 @@ */ public interface Config { + /** + * Create a {@link ConfigValue} to access the underlying configuration. + * + * @param key the property key + */ + ConfigValue access(String key); + /** * Resolves the value configured for the given key. * diff --git a/api/src/main/java/io/microprofile/config/ConfigValue.java b/api/src/main/java/io/microprofile/config/ConfigValue.java new file mode 100644 index 0000000..9231821 --- /dev/null +++ b/api/src/main/java/io/microprofile/config/ConfigValue.java @@ -0,0 +1,130 @@ +/* + * 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 io.microprofile.config; + + +import java.util.concurrent.TimeUnit; + +/** + * Accessor to a configured value. + * It follows a builder pattern. + * + * Accessing the configured value is finally done via {@link #getValue()} + * + * @author Mark Struberg + * @author Gerhard Petracek + * @author Ron Smeral + */ +public interface ConfigValue { + + /** + * Sets the type of the configuration entry to the given class and returns this builder. + * The default type of a ConfigValue is {@code String}. + * + * @param clazz The target type + * @param The target type + * @return This builder as a typed ConfigValue + */ + ConfigValue as(Class clazz); + + /** + * Sets the default value to use in case the resolution returns null. + * @param value the default value + * @return This builder + */ + ConfigValue withDefault(T value); + + /** + * Sets the default value to use in case the resolution returns null. Converts the given String to the type of + * this resolver using the same method as used for the configuration entries. + * @param value string value to be converted and used as default + * @return This builder + */ + ConfigValue withStringDefault(String value); + + /** + * Specify that a resolved value will get cached for a certain amount of time. + * After the time expires the next {@link #getValue()} will again resolve the value + * from the underlying {@link Config}. + * + * @param value the amount of the TimeUnit to wait + * @param timeUnit the TimeUnit for the value + * + * @return This builder + */ + ConfigValue cacheFor(long value, TimeUnit timeUnit); + + /** + * Whether to evaluate variables in configured values. + * A variable starts with '${' and ends with '}', e.g. + *
+     * mycompany.some.url=${myserver.host}/some/path
+     * myserver.host=http://localhost:8081
+     * 
+ * If 'evaluateVariables' is enabled, the result for the above key + * {@code "mycompany.some.url"} would be: + * {@code "http://localhost:8081/some/path"} + * @param evaluateVariables whether to evaluate variables in values or not + * @return This builder + */ + ConfigValue evaluateVariables(boolean evaluateVariables); + + /** + * Appends the resolved value of the given property to the key of this builder. + * TODO further explain. + * @return This builder + */ + ConfigValue withLookupChain(String... postfixNames); + + /** + * Whether to log picking up any value changes as INFO. + * + * @return This builder + */ + ConfigValue logChanges(boolean logChanges); + + /** + * Returns the converted resolved filtered value. + * @return the resolved value + */ + T getValue(); + + /** + * Returns the key given in {@link Config#access(String)}. + * @return the original key + */ + String getKey(); + + /** + * Returns the actual key which led to successful resolution and corresponds to the resolved value. This applies + * only when {@link #withLookupChain(String...)} is used. + * Otherwise the resolved key should always be equal to the original key. + * This method is provided for cases, when arameterized resolution is + * requested but the value for such appended key is not found and some of the fallback keys is used. + * + * This should be called only after calling {@link #getValue()} otherwise the value is undefined (but likely + * null). + */ + String getResolvedKey(); + + /** + * Returns the default value provided by {@link #withDefault(Object)} or {@link #withStringDefault(String)}. + * Returns null if no default was provided. + * @return the default value or {@code null} + */ + T getDefaultValue(); +} diff --git a/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java b/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java index 6aa702c..bab3494 100644 --- a/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java +++ b/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java @@ -29,6 +29,7 @@ import java.util.logging.Logger; import io.microprofile.config.Config; +import io.microprofile.config.ConfigValue; import io.microprofile.config.spi.ConfigFilter; import io.microprofile.config.spi.ConfigSource; import io.microprofile.config.spi.Converter; @@ -104,6 +105,10 @@ private Converter getConverter(Class asType) { return converter; } + public ConfigValue access(String key) { + return new ConfigValueImpl<>(this, key); + } + @Override public Map getAllProperties() { Map result = new HashMap(); diff --git a/impl/src/main/java/org/apache/geronimo/config/ConfigValueImpl.java b/impl/src/main/java/org/apache/geronimo/config/ConfigValueImpl.java new file mode 100644 index 0000000..623390c --- /dev/null +++ b/impl/src/main/java/org/apache/geronimo/config/ConfigValueImpl.java @@ -0,0 +1,219 @@ +/* + * 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.geronimo.config; + +import io.microprofile.config.ConfigValue; +import io.microprofile.config.spi.Converter; + +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * @author Mark Struberg + */ +public class ConfigValueImpl implements ConfigValue { + private static final Logger logger = Logger.getLogger(ConfigValueImpl.class.getName()); + + private final ConfigImpl config; + + private String keyOriginal; + + private String keyResolved; + + private Class configEntryType = String.class; + + private String[] lookupChain; + + private boolean withDefault = false; + private T defaultValue; + + + private Converter converter; + + private boolean evaluateVariables = false; + + private boolean logChanges = false; + + private long cacheTimeMs = -1; + private volatile long reloadAfter = -1; + private T lastValue = null; + + public ConfigValueImpl(ConfigImpl config, String key) { + this.config = config; + this.keyOriginal = key; + } + + @Override + public ConfigValue as(Class clazz) { + configEntryType = clazz; + this.converter = null; + return (ConfigValue) this; + } + + @Override + public ConfigValue withDefault(T value) { + defaultValue = value; + withDefault = true; + return this; + } + + @Override + public ConfigValue withStringDefault(String value) { + if (value == null || value.isEmpty()) + { + throw new RuntimeException("Empty String or null supplied as string-default value for property " + + keyOriginal); + } + + defaultValue = convert(value); + withDefault = true; + return this; + } + + @Override + public ConfigValue cacheFor(long value, TimeUnit timeUnit) { + this.cacheTimeMs = timeUnit.toMillis(value); + return this; + } + + @Override + public ConfigValue evaluateVariables(boolean evaluateVariables) { + this.evaluateVariables = evaluateVariables; + return this; + } + + @Override + public ConfigValue withLookupChain(String... postfixNames) { + this.lookupChain = postfixNames; + return this; + } + + @Override + public ConfigValue logChanges(boolean logChanges) { + this.logChanges = logChanges; + return this; + } + + @Override + public T getValue() { + long now = -1; + if (cacheTimeMs > 0) + { + now = System.currentTimeMillis(); + if (now <= reloadAfter) + { + return lastValue; + } + } + + String valueStr = resolveStringValue(); + T value = convert(valueStr); + + if (withDefault) + { + value = fallbackToDefaultIfEmpty(keyResolved, value, defaultValue); + } + + if (logChanges && (value != null && !value.equals(lastValue) || (value == null && lastValue != null)) ) + { + logger.log(Level.INFO, "New value {0} for key {1}.", + new Object[]{config.filterConfigValueForLog(keyOriginal, valueStr), keyOriginal}); + } + + lastValue = value; + + if (cacheTimeMs > 0) + { + reloadAfter = now + cacheTimeMs; + } + + return value; + } + + private String resolveStringValue() { + //X TODO implement lookupChain + + String value = config.getValue(keyOriginal); + if (evaluateVariables) + { + // recursively resolve any ${varName} in the value + int startVar = 0; + while ((startVar = value.indexOf("${", startVar)) >= 0) + { + int endVar = value.indexOf("}", startVar); + if (endVar <= 0) + { + break; + } + String varName = value.substring(startVar + 2, endVar); + if (varName.isEmpty()) + { + break; + } + String variableValue = config.access(varName).evaluateVariables(true).withLookupChain(lookupChain).getValue(); + if (variableValue != null) + { + value = value.replace("${" + varName + "}", variableValue); + } + startVar++; + } + } + return value; + } + + @Override + public String getKey() { + return keyOriginal; + } + + @Override + public String getResolvedKey() { + return keyResolved; + } + + @Override + public T getDefaultValue() { + return defaultValue; + } + + private T convert(String value) { + if (String.class == configEntryType) { + return (T) value; + } + + Converter converter = config.getConverters().get(configEntryType); + if (converter == null) { + throw new IllegalStateException("No Converter for type " + configEntryType); + } + + return (T) converter.convert(value); + } + + private T fallbackToDefaultIfEmpty(String key, T value, T defaultValue) { + if (value == null || (value instanceof String && ((String)value).isEmpty())) + { + logger.log(Level.FINE, "no configured value found for key {0}, using default value {1}.", + new Object[]{key, defaultValue}); + + return defaultValue; + } + + return value; + } + +} diff --git a/impl/src/main/java/org/apache/geronimo/config/DefaultConfigProvider.java b/impl/src/main/java/org/apache/geronimo/config/DefaultConfigProvider.java index 07605f9..c7be82a 100644 --- a/impl/src/main/java/org/apache/geronimo/config/DefaultConfigProvider.java +++ b/impl/src/main/java/org/apache/geronimo/config/DefaultConfigProvider.java @@ -30,7 +30,8 @@ */ public class DefaultConfigProvider implements ConfigProvider.SPI { - protected static Map> configs = Collections.synchronizedMap(new WeakHashMap>()); + protected static Map> configs + = Collections.synchronizedMap(new WeakHashMap>()); @Override @@ -69,7 +70,7 @@ protected Config createConfig(ClassLoader forClassLoader) { private void registerConfig(Config config, ClassLoader forClassLoader) { synchronized (DefaultConfigProvider.class) { - configs.put(forClassLoader, new WeakReference(config)); + configs.put(forClassLoader, new WeakReference<>(config)); } } diff --git a/tck/src/main/java/org/apache/geronimo/config/tck/ConfigValueTest.java b/tck/src/main/java/org/apache/geronimo/config/tck/ConfigValueTest.java new file mode 100644 index 0000000..568650d --- /dev/null +++ b/tck/src/main/java/org/apache/geronimo/config/tck/ConfigValueTest.java @@ -0,0 +1,132 @@ +/* + * 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.geronimo.config.tck; + +import io.microprofile.config.Config; +import io.microprofile.config.ConfigProvider; +import io.microprofile.config.ConfigValue; +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.util.concurrent.TimeUnit; + +/** + * @author Mark Struberg + */ +public class ConfigValueTest { + + private Config config = ConfigProvider.getConfig(); + + @Test + public void testGetValue() { + Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.key1").getValue(), "value1"); + } + + @Test + public void testGetValueWithDefault() { + ConfigValue cfga = config.access("tck.config.test.javaconfig.configvalue.withdefault.notexisting") + .as(Integer.class) + .withDefault(Integer.valueOf(1234)); + + Assert.assertEquals(cfga.getValue(), Integer.valueOf(1234)); + } + + @Test + public void testGetValueWithStringDefault() { + ConfigValue cfga = config.access("tck.config.test.javaconfig.configvalue.withdefault.notexisting") + .as(Integer.class) + .withStringDefault("1234"); + + Assert.assertEquals(cfga.getValue(), Integer.valueOf(1234)); + } + + @Test + public void testIntegerConverter() { + Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.integer").as(Integer.class).getValue(), Integer.valueOf(1234)); + } + + @Test + public void testLongConverter() { + Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.long").as(Long.class).getValue(), Long.valueOf(1234567890123456L)); + } + + @Test + public void testFloatConverter() { + Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.float").as(Float.class).getValue(), Float.valueOf(12.34f)); + } + + @Test + public void testDoubleonverter() { + Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.double").as(Double.class).getValue(), Double.valueOf(12.34567890123456)); + } + + @Test + public void testBooleanConverter() { + Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.true").as(Boolean.class).getValue(), Boolean.TRUE); + Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.true_uppercase").as(Boolean.class).getValue(), Boolean.TRUE); + Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.true_mixedcase").as(Boolean.class).getValue(), Boolean.TRUE); + Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.false").as(Boolean.class).getValue(), Boolean.FALSE); + + Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.one").as(Boolean.class).getValue(), Boolean.TRUE); + Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.zero").as(Boolean.class).getValue(), Boolean.FALSE); + Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.seventeen").as(Boolean.class).getValue(), Boolean.FALSE); + + Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.yes").as(Boolean.class).getValue(), Boolean.TRUE); + Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.yes_uppercase").as(Boolean.class).getValue(), Boolean.TRUE); + Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.yes_mixedcase").as(Boolean.class).getValue(), Boolean.TRUE); + + Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.y").as(Boolean.class).getValue(), Boolean.TRUE); + Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.y_uppercase").as(Boolean.class).getValue(), Boolean.TRUE); + + Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.ja").as(Boolean.class).getValue(), Boolean.TRUE); + Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.ja_uppercase").as(Boolean.class).getValue(), Boolean.TRUE); + Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.ja_mixedcase").as(Boolean.class).getValue(), Boolean.TRUE); + Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.no_mixedcase").as(Boolean.class).getValue(), Boolean.FALSE); + + Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.j").as(Boolean.class).getValue(), Boolean.TRUE); + Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.j_uppercase").as(Boolean.class).getValue(), Boolean.TRUE); + Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.n_uppercase").as(Boolean.class).getValue(), Boolean.FALSE); + + Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.oui").as(Boolean.class).getValue(), Boolean.TRUE); + Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.oui_uppercase").as(Boolean.class).getValue(), Boolean.TRUE); + Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.oui_mixedcase").as(Boolean.class).getValue(), Boolean.TRUE); + } + + @Test + public void testCacheFor() throws Exception { + String key = "tck.config.cachefor.key"; + System.setProperty(key, "firstvalue"); + ConfigValue val = config.access(key).cacheFor(30, TimeUnit.MILLISECONDS); + Assert.assertEquals(val.getValue(), "firstvalue"); + + // immediately change the value + System.setProperty(key, "secondvalue"); + + // we should still see the first value, because it is cached! + Assert.assertEquals(val.getValue(), "firstvalue"); + + // but now let's wait a bit + Thread.sleep(40); + Assert.assertEquals(val.getValue(), "secondvalue"); + } + + @Test + public void testWithVariable() throws Exception { + ConfigValue val = config.access("tck.config.test.javaconfig.configvalue.withvariable.key").evaluateVariables(true); + Assert.assertEquals(val.getValue(), "This key needs the perfect value!"); + } +} From 993542f53e72dc879bd5e472d0f263f97ab848ce Mon Sep 17 00:00:00 2001 From: Mark Struberg Date: Tue, 15 Nov 2016 11:01:09 +0100 Subject: [PATCH 04/29] adding Converter to ConfigBuilder --- .../java/io/microprofile/config/ConfigProvider.java | 2 ++ .../apache/geronimo/config/DefaultConfigBuilder.java | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/api/src/main/java/io/microprofile/config/ConfigProvider.java b/api/src/main/java/io/microprofile/config/ConfigProvider.java index d693a06..e679c15 100644 --- a/api/src/main/java/io/microprofile/config/ConfigProvider.java +++ b/api/src/main/java/io/microprofile/config/ConfigProvider.java @@ -21,6 +21,7 @@ import io.microprofile.config.spi.ConfigFilter; import io.microprofile.config.spi.ConfigSource; +import io.microprofile.config.spi.Converter; /** *

This is the central class to access a {@link Config}.

@@ -109,6 +110,7 @@ public interface ConfigBuilder { ConfigBuilder forClassLoader(ClassLoader loader); ConfigBuilder withSources(ConfigSource... sources); ConfigBuilder withFilters(ConfigFilter... filters); + ConfigBuilder withConverters(Converter... filters); Config build(); } diff --git a/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java b/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java index bd9afa2..3988375 100644 --- a/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java +++ b/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java @@ -21,6 +21,7 @@ import io.microprofile.config.spi.ConfigFilter; import io.microprofile.config.spi.ConfigSource; import io.microprofile.config.spi.ConfigSourceProvider; +import io.microprofile.config.spi.Converter; import org.apache.geronimo.config.configsource.PropertyFileConfigSourceProvider; import org.apache.geronimo.config.configsource.SystemEnvConfigSource; import org.apache.geronimo.config.configsource.SystemPropertyConfigSource; @@ -40,6 +41,7 @@ public class DefaultConfigBuilder implements ConfigProvider.ConfigBuilder { private ClassLoader forClassLoader; private final List sources = new ArrayList<>(); private final List filters = new ArrayList<>(); + private final List> converters = new ArrayList<>(); private boolean ignoreDefaultSources = false; @Override @@ -66,6 +68,12 @@ public ConfigProvider.ConfigBuilder withFilters(final ConfigFilter... filters) { return this; } + @Override + public ConfigProvider.ConfigBuilder withConverters(Converter... converters) { + this.converters.addAll(asList(converters)); + return this; + } + @Override public Config build() { List configSources = new ArrayList<>(); @@ -100,6 +108,10 @@ public Config build() { config.addConfigFilter(filter); } + for (Converter converter : converters) { + config.addConverter(converter); + } + return config; } From be0ae251b3b5461e4f8a8901a4ee3dfe8c3f826d Mon Sep 17 00:00:00 2001 From: Mark Struberg Date: Sun, 15 Jan 2017 20:35:17 +0100 Subject: [PATCH 05/29] improve JavaDoc --- .../main/java/io/microprofile/config/ConfigProvider.java | 7 ++++--- pom.xml | 4 ++++ spec/pom.xml | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/api/src/main/java/io/microprofile/config/ConfigProvider.java b/api/src/main/java/io/microprofile/config/ConfigProvider.java index e679c15..7e8c035 100644 --- a/api/src/main/java/io/microprofile/config/ConfigProvider.java +++ b/api/src/main/java/io/microprofile/config/ConfigProvider.java @@ -63,7 +63,7 @@ public class ConfigProvider { * Provide a {@link Config} based on all {@link ConfigSource}s * of the current Thread Context ClassLoader (TCCL) * - *

There is exactly a single Config instance per ClassLoader

+ *

There is exactly a single Config instance per Application

*/ public static Config getConfig() { return instance.getConfig(); @@ -73,7 +73,7 @@ public static Config getConfig() { * Provide a {@link Config} based on all {@link ConfigSource}s * of the given ClassLoader. * - *

There is exactly a single Config instance per ClassLoader

+ *

There is exactly a single Config instance per Application. The Application get's identified via a ClassLoader

*/ public static Config getConfig(ClassLoader forClassLoader) { return instance.getConfig(forClassLoader); @@ -85,7 +85,8 @@ public static Config getConfig(ClassLoader forClassLoader) { * {@link ConfigSource} nor any {@link ConfigFilter}. * Those have to be added manually. * - * The ConfigProvider will not manage the Config instance internally + * The ConfigProvider will not manage the Config instance internally. + * That means that {@link #getConfig()} does not pick up a Config created that way. */ public static ConfigBuilder newConfig() { return instance.newConfig(); diff --git a/pom.xml b/pom.xml index 1ac5b48..8721e88 100644 --- a/pom.xml +++ b/pom.xml @@ -31,6 +31,10 @@ 0.1-SNAPSHOT pom + + Apache License v 2.0 + + 3.1.0 diff --git a/spec/pom.xml b/spec/pom.xml index 416f9c5..7faf60c 100644 --- a/spec/pom.xml +++ b/spec/pom.xml @@ -35,7 +35,7 @@ 1.5.3 1.5.0-alpha.10.1 - ALv2 + Apache License v 2.0 MMMM dd, yyyy ${maven.build.timestamp} From b82524b838236297b52c23ae91919a8600176979 Mon Sep 17 00:00:00 2001 From: Mark Struberg Date: Sun, 15 Jan 2017 20:54:00 +0100 Subject: [PATCH 06/29] adopt License for microprofile usage --- NOTICE | 5 ++--- api/pom.xml | 22 +++++++++++++------ .../java/io/microprofile/config/Config.java | 8 +++---- .../microprofile/config/ConfigProvider.java | 8 +++---- .../io/microprofile/config/ConfigValue.java | 8 +++---- .../microprofile/config/spi/ConfigFilter.java | 13 +++++------ .../microprofile/config/spi/ConfigSource.java | 8 +++---- .../config/spi/ConfigSourceProvider.java | 13 +++++------ .../io/microprofile/config/spi/Converter.java | 13 +++++------ pom.xml | 7 +++++- spec/pom.xml | 22 +++++++++++++------ spec/src/main/asciidoc/architecture.asciidoc | 8 +++---- spec/src/main/asciidoc/configfilters.asciidoc | 8 +++---- spec/src/main/asciidoc/configsources.asciidoc | 8 +++---- spec/src/main/asciidoc/converters.asciidoc | 8 +++---- spec/src/main/asciidoc/license-alv2.asciidoc | 8 +++---- .../microprofile-config-spec.asciidoc | 13 +++++------ tck/pom.xml | 22 +++++++++++++------ 18 files changed, 113 insertions(+), 89 deletions(-) diff --git a/NOTICE b/NOTICE index 27e30dd..451c174 100644 --- a/NOTICE +++ b/NOTICE @@ -1,5 +1,4 @@ -Apache Geronimo Configuration -Copyright 2016 The Apache Software Foundation +Copyright 2016-2017 original author and authors This product includes software developed at -The Apache Software Foundation (http://www.apache.org/). +The Apache Software Foundation (http://www.apache.org/). \ No newline at end of file diff --git a/api/pom.xml b/api/pom.xml index 7411717..5a5765b 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -1,12 +1,11 @@ - + diff --git a/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java b/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java index 3988375..a84ac00 100644 --- a/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java +++ b/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java @@ -38,7 +38,7 @@ * @author Mark Struberg */ public class DefaultConfigBuilder implements ConfigProvider.ConfigBuilder { - private ClassLoader forClassLoader; + protected ClassLoader forClassLoader; private final List sources = new ArrayList<>(); private final List filters = new ArrayList<>(); private final List> converters = new ArrayList<>(); @@ -78,7 +78,9 @@ public ConfigProvider.ConfigBuilder withConverters(Converter... converters) { public Config build() { List configSources = new ArrayList<>(); - configSources.addAll(getBuiltInConfigSources(forClassLoader)); + if (!ignoreDefaultSources) { + configSources.addAll(getBuiltInConfigSources(forClassLoader)); + } configSources.addAll(sources); if (!ignoreDefaultSources) { diff --git a/impl/src/main/java/org/apache/geronimo/config/DefaultConfigProvider.java b/impl/src/main/java/org/apache/geronimo/config/DefaultConfigProvider.java index c7be82a..03adbff 100644 --- a/impl/src/main/java/org/apache/geronimo/config/DefaultConfigProvider.java +++ b/impl/src/main/java/org/apache/geronimo/config/DefaultConfigProvider.java @@ -59,7 +59,7 @@ public Config getConfig(ClassLoader forClassLoader) { return config; } - private Config existingConfig(ClassLoader forClassLoader) { + Config existingConfig(ClassLoader forClassLoader) { WeakReference configRef = configs.get(forClassLoader); return configRef != null ? configRef.get() : null; } @@ -68,7 +68,7 @@ protected Config createConfig(ClassLoader forClassLoader) { return newConfig().forClassLoader(forClassLoader).build(); } - private void registerConfig(Config config, ClassLoader forClassLoader) { + void registerConfig(Config config, ClassLoader forClassLoader) { synchronized (DefaultConfigProvider.class) { configs.put(forClassLoader, new WeakReference<>(config)); } @@ -79,6 +79,11 @@ public ConfigProvider.ConfigBuilder newConfig() { return new DefaultConfigBuilder(); } + @Override + public ConfigProvider.ConfigBuilder registerConfig() { + return new ManualApplicationConfigBuilder(this); + } + @Override public void releaseConfig(Config config) { if (config != null) { diff --git a/impl/src/main/java/org/apache/geronimo/config/ManualApplicationConfigBuilder.java b/impl/src/main/java/org/apache/geronimo/config/ManualApplicationConfigBuilder.java new file mode 100644 index 0000000..9b91edf --- /dev/null +++ b/impl/src/main/java/org/apache/geronimo/config/ManualApplicationConfigBuilder.java @@ -0,0 +1,49 @@ +/* + * 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.geronimo.config; + +import io.microprofile.config.Config; +import io.microprofile.config.ConfigProvider; + +/** + * @author Mark Struberg + */ +public class ManualApplicationConfigBuilder extends DefaultConfigBuilder { + private DefaultConfigProvider configProvider; + + public ManualApplicationConfigBuilder(DefaultConfigProvider configProvider) { + this.configProvider = configProvider; + } + + @Override + public synchronized Config build() { + Config config = super.build(); + ClassLoader cl = forClassLoader; + if (cl == null) { + cl = Thread.currentThread().getContextClassLoader(); + if (cl == null) { + cl = ConfigProvider.SPI.class.getClassLoader(); + } + } + Config oldConfig = configProvider.existingConfig(cl); + if (oldConfig != null) { + throw new IllegalStateException("This Application already has a registered Configuration!"); + } + configProvider.registerConfig(config, cl); + return config; + } +} diff --git a/tck/src/main/java/org/apache/geronimo/config/tck/ConfigProviderTest.java b/tck/src/main/java/org/apache/geronimo/config/tck/ConfigProviderTest.java index aafa3f5..09a9514 100644 --- a/tck/src/main/java/org/apache/geronimo/config/tck/ConfigProviderTest.java +++ b/tck/src/main/java/org/apache/geronimo/config/tck/ConfigProviderTest.java @@ -24,6 +24,7 @@ import io.microprofile.config.Config; import io.microprofile.config.ConfigProvider; +import org.apache.geronimo.config.tck.configsources.SampleYamlConfigSource; import org.testng.Assert; import org.testng.annotations.Test; @@ -91,6 +92,45 @@ public void testNonExistingConfigKey() { Assert.assertNull(config.getValue("tck.config.test.keydoesnotexist")); } + @Test + public void testRegisterManualConfig() { + // make sure we get a clean config + ConfigProvider.releaseConfig(ConfigProvider.getConfig()); + + ConfigProvider.registerConfig() + .ignoreDefaultSources() + .withSources(new SampleYamlConfigSource(null)) + .build(); + + Config config = ConfigProvider.getConfig(); + Assert.assertNotNull(config); + Assert.assertNotNull(config.getConfigSources()); + Assert.assertEquals(1, config.getConfigSources().length); + Assert.assertEquals(SampleYamlConfigSource.class, config.getConfigSources()[0].getClass()); + + Assert.assertEquals("yamlvalue1", config.getValue("tck.config.test.sampleyaml.key1")); + + Assert.assertNull(config.getValue("tck.config.test.javaconfig.properties.key1")); + + { + // try it again, Sam + // this time we should fail as we already have a Config registered for this application + try { + ConfigProvider.registerConfig() + .ignoreDefaultSources() + .withSources(new SampleYamlConfigSource(null)) + .build(); + + Assert.fail("We fail because subsequently registering another Config for the application is not allowed"); + } + catch (IllegalStateException ise) { + // all fine + } + } + + // clean up the dirt afterwards + ConfigProvider.releaseConfig(ConfigProvider.getConfig()); + } @Test public void testConfigProviderRelease() { From 0ee61e3578e277701cbd6f3028a3ebdedf5efe7c Mon Sep 17 00:00:00 2001 From: Mark Struberg Date: Sun, 15 Jan 2017 22:02:54 +0100 Subject: [PATCH 08/29] rename package to io.microprofile --- impl/debug-suite.xml | 2 +- .../microprofile}/config/tck/ConfigFilterTest.java | 2 +- .../microprofile}/config/tck/ConfigProviderTest.java | 4 ++-- .../microprofile}/config/tck/ConfigSourceProviderTest.java | 2 +- .../microprofile}/config/tck/ConfigValueTest.java | 2 +- .../microprofile}/config/tck/ConverterTest.java | 2 +- .../microprofile}/config/tck/CustomConfigSourceTest.java | 2 +- .../config/tck/configfilters/PasswordConfigFilter.java | 2 +- .../config/tck/configsources/CustomConfigSourceProvider.java | 2 +- .../config/tck/configsources/CustomDbConfigSource.java | 2 +- .../config/tck/configsources/SampleYamlConfigSource.java | 2 +- .../microprofile}/config/tck/converters/Duck.java | 2 +- .../microprofile}/config/tck/converters/DuckConverter.java | 2 +- .../META-INF/services/io.microprofile.config.spi.ConfigFilter | 2 +- .../META-INF/services/io.microprofile.config.spi.ConfigSource | 2 +- .../services/io.microprofile.config.spi.ConfigSourceProvider | 2 +- 16 files changed, 17 insertions(+), 17 deletions(-) rename tck/src/main/java/{org/apache/geronimo => io/microprofile}/config/tck/ConfigFilterTest.java (97%) rename tck/src/main/java/{org/apache/geronimo => io/microprofile}/config/tck/ConfigProviderTest.java (97%) rename tck/src/main/java/{org/apache/geronimo => io/microprofile}/config/tck/ConfigSourceProviderTest.java (96%) rename tck/src/main/java/{org/apache/geronimo => io/microprofile}/config/tck/ConfigValueTest.java (99%) rename tck/src/main/java/{org/apache/geronimo => io/microprofile}/config/tck/ConverterTest.java (97%) rename tck/src/main/java/{org/apache/geronimo => io/microprofile}/config/tck/CustomConfigSourceTest.java (96%) rename tck/src/main/java/{org/apache/geronimo => io/microprofile}/config/tck/configfilters/PasswordConfigFilter.java (96%) rename tck/src/main/java/{org/apache/geronimo => io/microprofile}/config/tck/configsources/CustomConfigSourceProvider.java (97%) rename tck/src/main/java/{org/apache/geronimo => io/microprofile}/config/tck/configsources/CustomDbConfigSource.java (97%) rename tck/src/main/java/{org/apache/geronimo => io/microprofile}/config/tck/configsources/SampleYamlConfigSource.java (96%) rename tck/src/main/java/{org/apache/geronimo => io/microprofile}/config/tck/converters/Duck.java (95%) rename tck/src/main/java/{org/apache/geronimo => io/microprofile}/config/tck/converters/DuckConverter.java (95%) diff --git a/impl/debug-suite.xml b/impl/debug-suite.xml index 1164b05..10e8976 100644 --- a/impl/debug-suite.xml +++ b/impl/debug-suite.xml @@ -24,7 +24,7 @@ - + diff --git a/tck/src/main/java/org/apache/geronimo/config/tck/ConfigFilterTest.java b/tck/src/main/java/io/microprofile/config/tck/ConfigFilterTest.java similarity index 97% rename from tck/src/main/java/org/apache/geronimo/config/tck/ConfigFilterTest.java rename to tck/src/main/java/io/microprofile/config/tck/ConfigFilterTest.java index 683b3a7..d41b07d 100644 --- a/tck/src/main/java/org/apache/geronimo/config/tck/ConfigFilterTest.java +++ b/tck/src/main/java/io/microprofile/config/tck/ConfigFilterTest.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.geronimo.config.tck; +package io.microprofile.config.tck; import io.microprofile.config.Config; import io.microprofile.config.ConfigProvider; diff --git a/tck/src/main/java/org/apache/geronimo/config/tck/ConfigProviderTest.java b/tck/src/main/java/io/microprofile/config/tck/ConfigProviderTest.java similarity index 97% rename from tck/src/main/java/org/apache/geronimo/config/tck/ConfigProviderTest.java rename to tck/src/main/java/io/microprofile/config/tck/ConfigProviderTest.java index 09a9514..6b9a4b0 100644 --- a/tck/src/main/java/org/apache/geronimo/config/tck/ConfigProviderTest.java +++ b/tck/src/main/java/io/microprofile/config/tck/ConfigProviderTest.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.geronimo.config.tck; +package io.microprofile.config.tck; import java.net.URL; import java.net.URLClassLoader; @@ -24,7 +24,7 @@ import io.microprofile.config.Config; import io.microprofile.config.ConfigProvider; -import org.apache.geronimo.config.tck.configsources.SampleYamlConfigSource; +import io.microprofile.config.tck.configsources.SampleYamlConfigSource; import org.testng.Assert; import org.testng.annotations.Test; diff --git a/tck/src/main/java/org/apache/geronimo/config/tck/ConfigSourceProviderTest.java b/tck/src/main/java/io/microprofile/config/tck/ConfigSourceProviderTest.java similarity index 96% rename from tck/src/main/java/org/apache/geronimo/config/tck/ConfigSourceProviderTest.java rename to tck/src/main/java/io/microprofile/config/tck/ConfigSourceProviderTest.java index 664d27d..28a65a9 100644 --- a/tck/src/main/java/org/apache/geronimo/config/tck/ConfigSourceProviderTest.java +++ b/tck/src/main/java/io/microprofile/config/tck/ConfigSourceProviderTest.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.geronimo.config.tck; +package io.microprofile.config.tck; import io.microprofile.config.Config; import io.microprofile.config.ConfigProvider; diff --git a/tck/src/main/java/org/apache/geronimo/config/tck/ConfigValueTest.java b/tck/src/main/java/io/microprofile/config/tck/ConfigValueTest.java similarity index 99% rename from tck/src/main/java/org/apache/geronimo/config/tck/ConfigValueTest.java rename to tck/src/main/java/io/microprofile/config/tck/ConfigValueTest.java index 568650d..575f00a 100644 --- a/tck/src/main/java/org/apache/geronimo/config/tck/ConfigValueTest.java +++ b/tck/src/main/java/io/microprofile/config/tck/ConfigValueTest.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.geronimo.config.tck; +package io.microprofile.config.tck; import io.microprofile.config.Config; import io.microprofile.config.ConfigProvider; diff --git a/tck/src/main/java/org/apache/geronimo/config/tck/ConverterTest.java b/tck/src/main/java/io/microprofile/config/tck/ConverterTest.java similarity index 97% rename from tck/src/main/java/org/apache/geronimo/config/tck/ConverterTest.java rename to tck/src/main/java/io/microprofile/config/tck/ConverterTest.java index dfa8e0b..bbb0419 100644 --- a/tck/src/main/java/org/apache/geronimo/config/tck/ConverterTest.java +++ b/tck/src/main/java/io/microprofile/config/tck/ConverterTest.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.geronimo.config.tck; +package io.microprofile.config.tck; import io.microprofile.config.Config; import io.microprofile.config.ConfigProvider; diff --git a/tck/src/main/java/org/apache/geronimo/config/tck/CustomConfigSourceTest.java b/tck/src/main/java/io/microprofile/config/tck/CustomConfigSourceTest.java similarity index 96% rename from tck/src/main/java/org/apache/geronimo/config/tck/CustomConfigSourceTest.java rename to tck/src/main/java/io/microprofile/config/tck/CustomConfigSourceTest.java index 83b0758..5a8d80d 100644 --- a/tck/src/main/java/org/apache/geronimo/config/tck/CustomConfigSourceTest.java +++ b/tck/src/main/java/io/microprofile/config/tck/CustomConfigSourceTest.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.geronimo.config.tck; +package io.microprofile.config.tck; import io.microprofile.config.Config; import io.microprofile.config.ConfigProvider; diff --git a/tck/src/main/java/org/apache/geronimo/config/tck/configfilters/PasswordConfigFilter.java b/tck/src/main/java/io/microprofile/config/tck/configfilters/PasswordConfigFilter.java similarity index 96% rename from tck/src/main/java/org/apache/geronimo/config/tck/configfilters/PasswordConfigFilter.java rename to tck/src/main/java/io/microprofile/config/tck/configfilters/PasswordConfigFilter.java index 4186b86..ef733cf 100644 --- a/tck/src/main/java/org/apache/geronimo/config/tck/configfilters/PasswordConfigFilter.java +++ b/tck/src/main/java/io/microprofile/config/tck/configfilters/PasswordConfigFilter.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.geronimo.config.tck.configfilters; +package io.microprofile.config.tck.configfilters; import io.microprofile.config.spi.ConfigFilter; diff --git a/tck/src/main/java/org/apache/geronimo/config/tck/configsources/CustomConfigSourceProvider.java b/tck/src/main/java/io/microprofile/config/tck/configsources/CustomConfigSourceProvider.java similarity index 97% rename from tck/src/main/java/org/apache/geronimo/config/tck/configsources/CustomConfigSourceProvider.java rename to tck/src/main/java/io/microprofile/config/tck/configsources/CustomConfigSourceProvider.java index 33691d0..2f2d0c4 100644 --- a/tck/src/main/java/org/apache/geronimo/config/tck/configsources/CustomConfigSourceProvider.java +++ b/tck/src/main/java/io/microprofile/config/tck/configsources/CustomConfigSourceProvider.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.geronimo.config.tck.configsources; +package io.microprofile.config.tck.configsources; import java.io.IOException; import java.net.URL; diff --git a/tck/src/main/java/org/apache/geronimo/config/tck/configsources/CustomDbConfigSource.java b/tck/src/main/java/io/microprofile/config/tck/configsources/CustomDbConfigSource.java similarity index 97% rename from tck/src/main/java/org/apache/geronimo/config/tck/configsources/CustomDbConfigSource.java rename to tck/src/main/java/io/microprofile/config/tck/configsources/CustomDbConfigSource.java index a5741d5..83e27a1 100644 --- a/tck/src/main/java/org/apache/geronimo/config/tck/configsources/CustomDbConfigSource.java +++ b/tck/src/main/java/io/microprofile/config/tck/configsources/CustomDbConfigSource.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.geronimo.config.tck.configsources; +package io.microprofile.config.tck.configsources; import java.util.HashMap; import java.util.Map; diff --git a/tck/src/main/java/org/apache/geronimo/config/tck/configsources/SampleYamlConfigSource.java b/tck/src/main/java/io/microprofile/config/tck/configsources/SampleYamlConfigSource.java similarity index 96% rename from tck/src/main/java/org/apache/geronimo/config/tck/configsources/SampleYamlConfigSource.java rename to tck/src/main/java/io/microprofile/config/tck/configsources/SampleYamlConfigSource.java index 2ea346b..4e7c4bb 100644 --- a/tck/src/main/java/org/apache/geronimo/config/tck/configsources/SampleYamlConfigSource.java +++ b/tck/src/main/java/io/microprofile/config/tck/configsources/SampleYamlConfigSource.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.geronimo.config.tck.configsources; +package io.microprofile.config.tck.configsources; import java.net.URL; import java.util.HashMap; diff --git a/tck/src/main/java/org/apache/geronimo/config/tck/converters/Duck.java b/tck/src/main/java/io/microprofile/config/tck/converters/Duck.java similarity index 95% rename from tck/src/main/java/org/apache/geronimo/config/tck/converters/Duck.java rename to tck/src/main/java/io/microprofile/config/tck/converters/Duck.java index 18d0fb0..23a0542 100644 --- a/tck/src/main/java/org/apache/geronimo/config/tck/converters/Duck.java +++ b/tck/src/main/java/io/microprofile/config/tck/converters/Duck.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.geronimo.config.tck.converters; +package io.microprofile.config.tck.converters; /** * @author Mark Struberg diff --git a/tck/src/main/java/org/apache/geronimo/config/tck/converters/DuckConverter.java b/tck/src/main/java/io/microprofile/config/tck/converters/DuckConverter.java similarity index 95% rename from tck/src/main/java/org/apache/geronimo/config/tck/converters/DuckConverter.java rename to tck/src/main/java/io/microprofile/config/tck/converters/DuckConverter.java index fe51b8d..b653fc1 100644 --- a/tck/src/main/java/org/apache/geronimo/config/tck/converters/DuckConverter.java +++ b/tck/src/main/java/io/microprofile/config/tck/converters/DuckConverter.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.geronimo.config.tck.converters; +package io.microprofile.config.tck.converters; import io.microprofile.config.spi.Converter; diff --git a/tck/src/main/resources/META-INF/services/io.microprofile.config.spi.ConfigFilter b/tck/src/main/resources/META-INF/services/io.microprofile.config.spi.ConfigFilter index 6aff602..81487b7 100644 --- a/tck/src/main/resources/META-INF/services/io.microprofile.config.spi.ConfigFilter +++ b/tck/src/main/resources/META-INF/services/io.microprofile.config.spi.ConfigFilter @@ -17,4 +17,4 @@ # under the License. # -org.apache.geronimo.config.tck.configfilters.PasswordConfigFilter \ No newline at end of file +io.microprofile.config.tck.configfilters.PasswordConfigFilter \ No newline at end of file diff --git a/tck/src/main/resources/META-INF/services/io.microprofile.config.spi.ConfigSource b/tck/src/main/resources/META-INF/services/io.microprofile.config.spi.ConfigSource index 16d2f7b..677a9fb 100644 --- a/tck/src/main/resources/META-INF/services/io.microprofile.config.spi.ConfigSource +++ b/tck/src/main/resources/META-INF/services/io.microprofile.config.spi.ConfigSource @@ -17,4 +17,4 @@ # under the License. # -org.apache.geronimo.config.tck.configsources.CustomDbConfigSource \ No newline at end of file +io.microprofile.config.tck.configsources.CustomDbConfigSource \ No newline at end of file diff --git a/tck/src/main/resources/META-INF/services/io.microprofile.config.spi.ConfigSourceProvider b/tck/src/main/resources/META-INF/services/io.microprofile.config.spi.ConfigSourceProvider index d2fc399..bbcd7a0 100644 --- a/tck/src/main/resources/META-INF/services/io.microprofile.config.spi.ConfigSourceProvider +++ b/tck/src/main/resources/META-INF/services/io.microprofile.config.spi.ConfigSourceProvider @@ -17,4 +17,4 @@ # under the License. # -org.apache.geronimo.config.tck.configsources.CustomConfigSourceProvider \ No newline at end of file +io.microprofile.config.tck.configsources.CustomConfigSourceProvider \ No newline at end of file From 1d9491361ec39a50a107ffb252f5b41ec0e6080f Mon Sep 17 00:00:00 2001 From: Mark Struberg Date: Sun, 15 Jan 2017 22:30:04 +0100 Subject: [PATCH 09/29] remove ConfigFilter as any secrets will be handled in an own proposal --- README.adoc | 2 +- .../java/io/microprofile/config/Config.java | 14 ---- .../microprofile/config/ConfigProvider.java | 2 - .../microprofile/config/spi/ConfigFilter.java | 52 ------------- .../apache/geronimo/config/ConfigImpl.java | 35 +-------- .../geronimo/config/ConfigValueImpl.java | 2 +- .../geronimo/config/DefaultConfigBuilder.java | 18 ----- spec/src/main/asciidoc/configfilters.asciidoc | 75 ------------------- .../microprofile-config-spec.asciidoc | 2 - .../config/tck/ConfigFilterTest.java | 48 ------------ .../configfilters/PasswordConfigFilter.java | 47 ------------ .../resources/META-INF/java-config.properties | 3 - .../io.microprofile.config.spi.ConfigFilter | 20 ----- 13 files changed, 4 insertions(+), 316 deletions(-) delete mode 100644 api/src/main/java/io/microprofile/config/spi/ConfigFilter.java delete mode 100644 spec/src/main/asciidoc/configfilters.asciidoc delete mode 100644 tck/src/main/java/io/microprofile/config/tck/ConfigFilterTest.java delete mode 100644 tck/src/main/java/io/microprofile/config/tck/configfilters/PasswordConfigFilter.java delete mode 100644 tck/src/main/resources/META-INF/services/io.microprofile.config.spi.ConfigFilter diff --git a/README.adoc b/README.adoc index 63fb9be..5f6c584 100644 --- a/README.adoc +++ b/README.adoc @@ -34,7 +34,7 @@ But be able to overwrite those default values from external. This very configuration approach has it's roots in the Apache OpenWebBeans internal SPI configuration. In 2010 it got moved over to the Apache MyFaces CODI project and enhanced to also fit the need of customer projects by Gerhard Petracek and Mark Struberg. -In 2012 we further enhanced it while moving CODI to the Apache DeltaSpike project. +In 2011 we further enhanced it while moving CODI to the Apache DeltaSpike project. Romain Manni-Bucau (Apache/Tomitribe), Ron Smeral (JBoss) and Anatole Tresch also gave appreciated input in the last years. == How it works diff --git a/api/src/main/java/io/microprofile/config/Config.java b/api/src/main/java/io/microprofile/config/Config.java index 628de45..76e2e55 100644 --- a/api/src/main/java/io/microprofile/config/Config.java +++ b/api/src/main/java/io/microprofile/config/Config.java @@ -79,20 +79,6 @@ public interface Config { */ Map getAllProperties(); - /** - * Filter the configured value. - * This can e.g. be used for decryption. - * @return the filtered value - */ - String filterConfigValue(String key, String value); - - /** - * Filter the configured value for logging. - * This can e.g. be used for displaying ***** instead of a real password. - * @return the filtered value - */ - String filterConfigValueForLog(String key, String value); - /** * @return all currently registered {@link ConfigSource}s */ diff --git a/api/src/main/java/io/microprofile/config/ConfigProvider.java b/api/src/main/java/io/microprofile/config/ConfigProvider.java index 4cbf7ce..ae0f690 100644 --- a/api/src/main/java/io/microprofile/config/ConfigProvider.java +++ b/api/src/main/java/io/microprofile/config/ConfigProvider.java @@ -19,7 +19,6 @@ import java.util.ServiceLoader; import java.util.logging.Logger; -import io.microprofile.config.spi.ConfigFilter; import io.microprofile.config.spi.ConfigSource; import io.microprofile.config.spi.Converter; @@ -122,7 +121,6 @@ public interface ConfigBuilder { ConfigBuilder ignoreDefaultSources(); ConfigBuilder forClassLoader(ClassLoader loader); ConfigBuilder withSources(ConfigSource... sources); - ConfigBuilder withFilters(ConfigFilter... filters); ConfigBuilder withConverters(Converter... filters); Config build(); } diff --git a/api/src/main/java/io/microprofile/config/spi/ConfigFilter.java b/api/src/main/java/io/microprofile/config/spi/ConfigFilter.java deleted file mode 100644 index 15a130b..0000000 --- a/api/src/main/java/io/microprofile/config/spi/ConfigFilter.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * See the NOTICE file distributed with this work for additional information - * regarding copyright ownership. - * The author 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 io.microprofile.config.spi; - -import io.microprofile.config.Config; - -/** - *

A filter which can be added to the - * {@link Config}. - * The filter can be used to decrypt config values or prepare - * values for logging.

- * - *

Registering a {@code ConfigFilter} can either be done via the - * {@code java.util.ServiceLoader} pattern or by manually adding it via - * {@link Config#addConfigFilter(ConfigFilter)}.

- * - * @author Mark Struberg - */ -public interface ConfigFilter -{ - /** - * Filter the given configuration value - * @param key - * @param value - * @return the filtered value or the original input String if no filter shall be applied - */ - String filterValue(String key, String value); - - /** - * Filter the given configuration value for usage in logs. - * This might be used to mask out passwords, etc. - * @param key - * @param value - * @return the filtered value or the original input String if no filter shall be applied - */ - String filterValueForLog(String key, String value); -} diff --git a/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java b/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java index bab3494..a9feb00 100644 --- a/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java +++ b/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java @@ -30,7 +30,6 @@ import io.microprofile.config.Config; import io.microprofile.config.ConfigValue; -import io.microprofile.config.spi.ConfigFilter; import io.microprofile.config.spi.ConfigSource; import io.microprofile.config.spi.Converter; import org.apache.geronimo.config.converters.BooleanConverter; @@ -48,7 +47,6 @@ public class ConfigImpl implements Config { protected Logger logger = Logger.getLogger(ConfigImpl.class.getName()); protected ConfigSource[] configSources = new ConfigSource[0]; - protected List configFilters = new ArrayList<>(); protected Map converters = new HashMap<>(); @@ -72,10 +70,10 @@ public String getValue(String key) { if (value != null) { if (logger.isLoggable(Level.FINE)) { logger.log(Level.FINE, "found value {0} for key {1} in ConfigSource {2}.", - new Object[]{filterConfigValueForLog(key, value), key, configSource.getConfigName()}); + new Object[]{value, key, configSource.getConfigName()}); } - return filterConfigValue(key, value); + return value; } } return null; @@ -118,34 +116,9 @@ public Map getAllProperties() { result.putAll(configSource.getProperties()); } - // now filter them - for (Map.Entry entries : result.entrySet()) { - entries.setValue(filterConfigValue(entries.getKey(), entries.getValue())); - } - return Collections.unmodifiableMap(result); } - @Override - public String filterConfigValue(String key, String value) { - String filteredValue = value; - - for (ConfigFilter filter : configFilters) { - filteredValue = filter.filterValue(key, filteredValue); - } - return filteredValue; - } - - @Override - public String filterConfigValueForLog(String key, String value) { - String logValue = value; - - for (ConfigFilter filter : configFilters) { - logValue = filter.filterValueForLog(key, logValue); - } - - return logValue; - } @Override public ConfigSource[] getConfigSources() { @@ -160,10 +133,6 @@ public synchronized void addConfigSources(List configSourcesToAdd) configSources = sortDescending(allConfigSources); } - public synchronized void addConfigFilter(ConfigFilter configFilter) { - configFilters.add(configFilter); - - } public synchronized void addConverter(Converter converter) { if (converter == null) { diff --git a/impl/src/main/java/org/apache/geronimo/config/ConfigValueImpl.java b/impl/src/main/java/org/apache/geronimo/config/ConfigValueImpl.java index 623390c..b552493 100644 --- a/impl/src/main/java/org/apache/geronimo/config/ConfigValueImpl.java +++ b/impl/src/main/java/org/apache/geronimo/config/ConfigValueImpl.java @@ -132,7 +132,7 @@ public T getValue() { if (logChanges && (value != null && !value.equals(lastValue) || (value == null && lastValue != null)) ) { logger.log(Level.INFO, "New value {0} for key {1}.", - new Object[]{config.filterConfigValueForLog(keyOriginal, valueStr), keyOriginal}); + new Object[]{valueStr, keyOriginal}); } lastValue = value; diff --git a/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java b/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java index a84ac00..2d504d3 100644 --- a/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java +++ b/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java @@ -18,7 +18,6 @@ import io.microprofile.config.Config; import io.microprofile.config.ConfigProvider; -import io.microprofile.config.spi.ConfigFilter; import io.microprofile.config.spi.ConfigSource; import io.microprofile.config.spi.ConfigSourceProvider; import io.microprofile.config.spi.Converter; @@ -40,7 +39,6 @@ public class DefaultConfigBuilder implements ConfigProvider.ConfigBuilder { protected ClassLoader forClassLoader; private final List sources = new ArrayList<>(); - private final List filters = new ArrayList<>(); private final List> converters = new ArrayList<>(); private boolean ignoreDefaultSources = false; @@ -62,12 +60,6 @@ public ConfigProvider.ConfigBuilder withSources(final ConfigSource... sources) { return this; } - @Override - public ConfigProvider.ConfigBuilder withFilters(final ConfigFilter... filters) { - this.filters.addAll(asList(filters)); - return this; - } - @Override public ConfigProvider.ConfigBuilder withConverters(Converter... converters) { this.converters.addAll(asList(converters)); @@ -100,16 +92,6 @@ public Config build() { ConfigImpl config = new ConfigImpl(); config.addConfigSources(configSources); - // also register all ConfigFilters - ServiceLoader configFilterLoader = ServiceLoader.load(ConfigFilter.class, forClassLoader); - for (ConfigFilter configFilter : configFilterLoader) { - config.addConfigFilter(configFilter); - } - - for (ConfigFilter filter : filters) { - config.addConfigFilter(filter); - } - for (Converter converter : converters) { config.addConverter(converter); } diff --git a/spec/src/main/asciidoc/configfilters.asciidoc b/spec/src/main/asciidoc/configfilters.asciidoc deleted file mode 100644 index b11f4e3..0000000 --- a/spec/src/main/asciidoc/configfilters.asciidoc +++ /dev/null @@ -1,75 +0,0 @@ -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// See the NOTICE file distributed with this work -// for additional information regarding copyright ownership. -// The author 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. -// - -[[configfilters]] -== ConfigFilters - -A `ConfigFilter` acts as a valve which is able to modify the configured values before they are returned to the caller. - -An implementation of the specification is not required to ship with any `ConfigFilters` enabled by default. - -A custom `ConfigFilter` must implement the interface `io.microprofile.config.spi.ConfigFilter` and is typically registered in a classpath resource `/META-INF/services/io.microprofile.config.spi.ConfigFilter` by including the fully-qualified class name of the custom implementation (well-known Java SE `java.util.ServiceLoader` mechanism). - -Alternatively a user can register a `ConfigFilter` manually via `void Config#addConfigFilter(ConfigFilter configFilterToAdd)`. - -=== Filtering a value for Usage - -A `ConfigFilter` can e.g. be used to decrypt a stored password on the fly: - -[source, java] ----- -public class PasswordDecryptionConfigFilter implements ConfigFilter { - @Override - public String filterValue(String key, String value) { - if (value != null && key.endsWith(".password")) { - return decrypt(value); - } - return value; - } - - @Override - public String filterValueForLog(String key, String value) { - // do nothing - return value; - } -} ----- - -=== Filtering a value for Logging - -To prevent passwords and other secret information from being printed out or logged, a `ConfigFilter` can be used to mask those values. - -[source, java] ----- -public class PasswordConfigFilter implements ConfigFilter { - @Override - public String filterValue(String key, String value) { - // do nothing - return value; - } - - @Override - public String filterValueForLog(String key, String value) { - if (value != null && - (key.contains("password") || key.contains("secret"))) { - return "*******"; // simply star-out the password - } - return value; - } -} - ----- diff --git a/spec/src/main/asciidoc/microprofile-config-spec.asciidoc b/spec/src/main/asciidoc/microprofile-config-spec.asciidoc index f01ac12..187c9a5 100644 --- a/spec/src/main/asciidoc/microprofile-config-spec.asciidoc +++ b/spec/src/main/asciidoc/microprofile-config-spec.asciidoc @@ -39,6 +39,4 @@ include::architecture.asciidoc[] include::configsources.asciidoc[] -include::configfilters.asciidoc[] - include::converters.asciidoc[] diff --git a/tck/src/main/java/io/microprofile/config/tck/ConfigFilterTest.java b/tck/src/main/java/io/microprofile/config/tck/ConfigFilterTest.java deleted file mode 100644 index d41b07d..0000000 --- a/tck/src/main/java/io/microprofile/config/tck/ConfigFilterTest.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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 io.microprofile.config.tck; - -import io.microprofile.config.Config; -import io.microprofile.config.ConfigProvider; -import org.testng.Assert; -import org.testng.annotations.Test; - -/** - * @author Mark Struberg - */ -public class ConfigFilterTest { - - @Test - public void testConfigFiltering() { - Config config = ConfigProvider.getConfig(); - - // unfiltered - Assert.assertEquals(config.getValue("tck.config.test.javaconfig.configfilter.my.secret"), "SOME_SECRET"); - - // filtered - Assert.assertEquals(config.getValue("tck.config.test.javaconfig.configfilter.my.password"), "some_password"); - } - - @Test - public void testConfigFiltering_ForLogging() { - Config config = ConfigProvider.getConfig(); - - Assert.assertEquals( - config.filterConfigValueForLog("tck.config.test.javaconfig.configfilter.my.password", - config.getValue("tck.config.test.javaconfig.configfilter.my.password")), "*******"); - } -} diff --git a/tck/src/main/java/io/microprofile/config/tck/configfilters/PasswordConfigFilter.java b/tck/src/main/java/io/microprofile/config/tck/configfilters/PasswordConfigFilter.java deleted file mode 100644 index ef733cf..0000000 --- a/tck/src/main/java/io/microprofile/config/tck/configfilters/PasswordConfigFilter.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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 io.microprofile.config.tck.configfilters; - -import io.microprofile.config.spi.ConfigFilter; - -/** - * @author Mark Struberg - */ -public class PasswordConfigFilter implements ConfigFilter { - @Override - public String filterValue(String key, String value) { - if (value != null && key.endsWith(".password")) { - return decrypt(value); - } - return value; - } - - @Override - public String filterValueForLog(String key, String value) { - if (value != null && - (key.contains("password") || key.contains("secret"))) { - return "*******"; // simply star-out the password - } - return value; - } - - private String decrypt(String value) { - // Just to modify the string. - // In reality the 'encryption' should be a bit stronger ;) - return value.toLowerCase(); - } -} diff --git a/tck/src/main/resources/META-INF/java-config.properties b/tck/src/main/resources/META-INF/java-config.properties index 879c8ee..8d478f9 100644 --- a/tck/src/main/resources/META-INF/java-config.properties +++ b/tck/src/main/resources/META-INF/java-config.properties @@ -24,9 +24,6 @@ tck.config.test.javaconfig.properties.key1=VALue1 tck.config.test.overwritten.in.custompropertyfile.key1=value from java-config.properties -tck.config.test.javaconfig.configfilter.my.secret = SOME_SECRET -tck.config.test.javaconfig.configfilter.my.password = SOME_PASSWORD - tck.config.test.javaconfig.converter.integervalue = 1234 tck.config.test.javaconfig.converter.floatvalue = 12.34 diff --git a/tck/src/main/resources/META-INF/services/io.microprofile.config.spi.ConfigFilter b/tck/src/main/resources/META-INF/services/io.microprofile.config.spi.ConfigFilter deleted file mode 100644 index 81487b7..0000000 --- a/tck/src/main/resources/META-INF/services/io.microprofile.config.spi.ConfigFilter +++ /dev/null @@ -1,20 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy current the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -io.microprofile.config.tck.configfilters.PasswordConfigFilter \ No newline at end of file From ca43fd814f144d670deee1ce2f478804fecc1150 Mon Sep 17 00:00:00 2001 From: Mark Struberg Date: Tue, 17 Jan 2017 08:40:59 +0100 Subject: [PATCH 10/29] tweak spec wording to say 'Application based on ClassLoader' --- spec/src/main/asciidoc/architecture.asciidoc | 21 +++++++++++++------- spec/src/main/asciidoc/license-alv2.asciidoc | 6 +----- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/spec/src/main/asciidoc/architecture.asciidoc b/spec/src/main/asciidoc/architecture.asciidoc index dfd96ed..13dd764 100644 --- a/spec/src/main/asciidoc/architecture.asciidoc +++ b/spec/src/main/asciidoc/architecture.asciidoc @@ -39,24 +39,31 @@ The `ConfigProvider` is the central class to access a configuration. It allows access to different configurations (represented by a `Config` instance) based on the application in which it is used. We distinguish 3 different ways to resolve a `Config` instance: -* A factory method `ConfigProvider#getConfig()` to create a `Config` object based on automatically picked up `ConfigSource` s from the current Thread Context ClassLoader classpath. - Subsequent calls to this method for a certain ClassLoader will return the same `Config` instance. +* A factory method `ConfigProvider#getConfig()` to create a `Config` object based on automatically picked up `ConfigSources` + of the Application identified by the current Thread Context ClassLoader classpath. + Subsequent calls to this method for a certain Application will return the same `Config` instance. -* A factory method `ConfigProvider#getConfig(ClassLoader forClassLoader)` to create a `Config` object based on automatically picked up `ConfigSource` s from a given ClassLoader. +* A factory method `ConfigProvider#getConfig(ClassLoader forClassLoader)` to create a `Config` object based on automatically picked up `ConfigSources` + of the Application identified by the given ClassLoader. This can be used if the Thread Context ClassLoader does not represent the correct layer. E.g. if you need the Config for a class in a shared EAR lib folder. - Subsequent calls to this method for a certain ClassLoader will return the same `Config` instance. + Subsequent calls to this method for a certain Application will return the same `Config` instance. * A factory method `ConfigProvider#newConfig()` to create an empty `Config` object which can be filled manually via a builder. This configuration instance will not be shared by the `ConfigProvider`. This method is intended be used if a IoT container or any other external Factory can be used to give access to a manually created shared `Config`. +* A factory method `ConfigProvider#registerConfig()` to create an empty `Config` object which can be filled manually via a builder. + This configuration instance *will* be shared by the `ConfigProvider`. + Any subsequent call to `ConfigProvider#getConfig()` will return the registered `Config` instance. + + All methods in the `ConfigProvider` and `Config` implementations are thread safe and reentrant. -If a `Config` is bound to a ClassLoader it must be made sure that it gets properly removed if the ClassLoader gets destroyed. -It must not create any memory leaks in that case. +If a `Config` is bound to an Application it is ensured that it gets properly removed if the Application gets destroyed. +The Config system deos not create any memory leaks in that case. -A `Config` can be release by calling `ConfigProvider#release(Config)`. +A `Config` can be release manually by calling `ConfigProvider#release(Config)`. ConfigSources which implement the `java.io.Closeable` interface will be properly destroyed. Any subsequent call to `ConfigProvider#getConfig()` or `ConfigProvider#getConfig(ClassLoader forClassLoader)` will result in a new `Config` instance. diff --git a/spec/src/main/asciidoc/license-alv2.asciidoc b/spec/src/main/asciidoc/license-alv2.asciidoc index 9dab241..ff9d5f6 100644 --- a/spec/src/main/asciidoc/license-alv2.asciidoc +++ b/spec/src/main/asciidoc/license-alv2.asciidoc @@ -28,11 +28,7 @@ Specification Lead: Mark Struberg Release: {revdate} -Copyright 2016 Original Authors, -Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. -Licensed to the Microprofile.io community. - - +Copyright 2016-2017 Original Authors, Licensed 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 From f880b0d523f0a86746086c5297bc355c86cc3afd Mon Sep 17 00:00:00 2001 From: Mark Struberg Date: Tue, 17 Jan 2017 09:52:33 +0100 Subject: [PATCH 11/29] rework spec. Also add Emily as she seems to be the designated feature leader within microprofile --- spec/src/main/asciidoc/architecture.asciidoc | 70 ++-------------- .../src/main/asciidoc/configexamples.asciidoc | 84 +++++++++++++++++++ .../src/main/asciidoc/configprovider.asciidoc | 53 ++++++++++++ spec/src/main/asciidoc/configsources.asciidoc | 12 ++- spec/src/main/asciidoc/converters.asciidoc | 4 +- spec/src/main/asciidoc/license-alv2.asciidoc | 2 +- .../microprofile-config-spec.asciidoc | 4 + 7 files changed, 158 insertions(+), 71 deletions(-) create mode 100644 spec/src/main/asciidoc/configexamples.asciidoc create mode 100644 spec/src/main/asciidoc/configprovider.asciidoc diff --git a/spec/src/main/asciidoc/architecture.asciidoc b/spec/src/main/asciidoc/architecture.asciidoc index 13dd764..b715436 100644 --- a/spec/src/main/asciidoc/architecture.asciidoc +++ b/spec/src/main/asciidoc/architecture.asciidoc @@ -24,54 +24,18 @@ It also defines a way to extend the configuration mechanism itself via a SPI (Se === Rational Released binaries often contain functionality which need to behave slightly differently depending on the deployment. -This might be different REST endpoints to talk with (e.g. depending on the customer for whom a WAR is deployed). +This might be different REST endpoints to talk to (e.g. depending on the customer for whom a WAR is deployed). Or it might even be different features which need to be switched on and off depending on the installation. All this must be possible without the need to re-package the whole application binary. -Microprofile-Config provides a way to achieve this goal by aggregating configuration from many different sources and presents a single merged view to the user. +Microprofile-Config provides a way to achieve this goal by aggregating configuration from many different <> and presents a single merged view to the user. This allows the application to bundle default configuration within the application. It also allows to override the defaults from outside, e.g. via an environment variable a Java system property or via Docker. Microprofile-Config also allows to implement and register own configuration sources in a portable way, e.g. for reading configuration values from a shared database in an application cluster. -=== Accessing a certain Configuration - -The `ConfigProvider` is the central class to access a configuration. -It allows access to different configurations (represented by a `Config` instance) based on the application in which it is used. -We distinguish 3 different ways to resolve a `Config` instance: - -* A factory method `ConfigProvider#getConfig()` to create a `Config` object based on automatically picked up `ConfigSources` - of the Application identified by the current Thread Context ClassLoader classpath. - Subsequent calls to this method for a certain Application will return the same `Config` instance. - -* A factory method `ConfigProvider#getConfig(ClassLoader forClassLoader)` to create a `Config` object based on automatically picked up `ConfigSources` - of the Application identified by the given ClassLoader. - This can be used if the Thread Context ClassLoader does not represent the correct layer. - E.g. if you need the Config for a class in a shared EAR lib folder. - Subsequent calls to this method for a certain Application will return the same `Config` instance. - -* A factory method `ConfigProvider#newConfig()` to create an empty `Config` object which can be filled manually via a builder. - This configuration instance will not be shared by the `ConfigProvider`. - This method is intended be used if a IoT container or any other external Factory can be used to give access to a manually created shared `Config`. - -* A factory method `ConfigProvider#registerConfig()` to create an empty `Config` object which can be filled manually via a builder. - This configuration instance *will* be shared by the `ConfigProvider`. - Any subsequent call to `ConfigProvider#getConfig()` will return the registered `Config` instance. - - -All methods in the `ConfigProvider` and `Config` implementations are thread safe and reentrant. - -If a `Config` is bound to an Application it is ensured that it gets properly removed if the Application gets destroyed. -The Config system deos not create any memory leaks in that case. - -A `Config` can be release manually by calling `ConfigProvider#release(Config)`. -ConfigSources which implement the `java.io.Closeable` interface will be properly destroyed. -Any subsequent call to `ConfigProvider#getConfig()` or `ConfigProvider#getConfig(ClassLoader forClassLoader)` will result in a new `Config` instance. - - -=== Configuration Lookup Mechanism Example The core Microprofile-Config mechanism is purely String/String based. -Type-safety is only provided on top of that by using the proper `Converter` before handing the value out to the caller. +Type-safety is only provided on top of that by using the proper <> before handing the value out to the caller. The configuration key might use dot-separated namespaces similar to Java package namespacing: @@ -81,31 +45,7 @@ com.acme.myproject.someserver.url = http://some.server/some/endpoint com.acme.myproject.someserver.port = 9085 com.acme.myproject.someserver.active = true com.acme.other.stuff.name = Karl +com.acme.myproject.notify.onerror=karl@mycompany,sue@mcompany ---- -An application can access this configuration via a `Config` instance. - -[source, java] ----- -public class ConfigUsageSample { - - public void useTheConfig() { - // get access to the Config instance - Config config = ConfigProvider.getConfig(); - String serverUrl = config.getValue("com.acme.myproject.someserver.url"); - Integer serverPort = config.getValue("com.acme.myproject.someserver.port", - Integer.class); - - callToServer(serverUrl, serverPort); - } -} ----- - -If you need to access a different server then you can e.g. change the configuration via a `-D` system property: - -[source, text] ----- -$> java -jar some.jar -Dcom.acme.myproject.someserver.url=http://other.server/other/endpoint ----- - -Note that the way to inject this configuration into the application can be extended by providing custom `ConfigSource` s. +Config keys are usually case sensitive. diff --git a/spec/src/main/asciidoc/configexamples.asciidoc b/spec/src/main/asciidoc/configexamples.asciidoc new file mode 100644 index 0000000..ab1a817 --- /dev/null +++ b/spec/src/main/asciidoc/configexamples.asciidoc @@ -0,0 +1,84 @@ +// +// Licensed under the Apache License, Version 2.0 (the "License"). +// See the NOTICE file distributed with this work +// for additional information regarding copyright ownership. +// The author 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. +// + +[[configexamples]] +== Configuration Usage Examples + +An application can access it's configured values via a `Config` instance. +Use the `ConfigProvider` to access the `Config` of an application. + +=== Simple Example + +[source, java] +---- +public class ConfigUsageSample { + + public void useTheConfig() { + // get access to the Config instance + Config config = ConfigProvider.getConfig(); + + String serverUrl = config.getValue("com.acme.myproject.someserver.url"); + Integer serverPort = config.getValue("com.acme.myproject.someserver.port", + Integer.class); + + callToServer(serverUrl, serverPort); + } +} +---- + +If you need to access a different server then you can e.g. change the configuration via a `-D` system property: + +[source, text] +---- +$> java -jar some.jar -Dcom.acme.myproject.someserver.url=http://other.server/other/endpoint +---- + +Note that the way to inject this configuration into the application can be extended by providing custom `ConfigSource` s. + + +=== Some advanced features + +It is also possible to dynamically pick up values which might change at runtime. +For example if the configured values get picked up from a custom <> which picks up it's values from a Database. + +[source, java] +---- +public class DynamicConfigUsageSample { + + private ConfigValue urlConfigCfg + = ConfigProvider.getConfig.access("com.acme.myproject.someserver.url") + .cacheFor(5, TimeUnit.MINUTES) + .logChanges(true) + .evaluateVariables(true); + + private ConfigValue urlPortCfg + = ConfigProvider.getConfig.access("com.acme.myproject.someserver.url") + .as(Integer.class) + .cacheFor(5, TimeUnit.MINUTES) + .logChanges(true) + .evaluateVariables(true) + .withDefault(8080); + + public void useTheConfig() { + callToServer(serverUrlCfg.getValue(), serverPortCfg.getValue()); + } +} +---- + +The `cacheFor(5, TimeUnit.MINUTES)` will have the `ConfigValue` behave like a local cache and thus reduce load on the configuration system. +5 minutes after `getValue()` got called the last time any fresh value will get picked up. +If `logChanges(true)` is set then any value change will get logged. \ No newline at end of file diff --git a/spec/src/main/asciidoc/configprovider.asciidoc b/spec/src/main/asciidoc/configprovider.asciidoc new file mode 100644 index 0000000..77c7285 --- /dev/null +++ b/spec/src/main/asciidoc/configprovider.asciidoc @@ -0,0 +1,53 @@ +// +// Licensed under the Apache License, Version 2.0 (the "License"). +// See the NOTICE file distributed with this work +// for additional information regarding copyright ownership. +// The author 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. +// + +[[configprovider]] +== Accessing or Creating a certain Configuration + +The `ConfigProvider` is the central class to access a configuration. +It allows access to different configurations (represented by a `Config` instance) based on the application in which it is used. +We distinguish 3 different ways to resolve a `Config` instance: + +* A factory method `ConfigProvider#getConfig()` to create a `Config` object based on automatically picked up `ConfigSources` + of the Application identified by the current Thread Context ClassLoader classpath. + Subsequent calls to this method for a certain Application will return the same `Config` instance. + +* A factory method `ConfigProvider#getConfig(ClassLoader forClassLoader)` to create a `Config` object based on automatically picked up `ConfigSources` + of the Application identified by the given ClassLoader. + This can be used if the Thread Context ClassLoader does not represent the correct layer. + E.g. if you need the Config for a class in a shared EAR lib folder. + Subsequent calls to this method for a certain Application will return the same `Config` instance. + +* A factory method `ConfigProvider#newConfig()` to create an empty `Config` object which can be filled manually via a builder. + This configuration instance will not be shared by the `ConfigProvider`. + This method is intended be used if a IoT container or any other external Factory can be used to give access to a manually created shared `Config`. + +* A factory method `ConfigProvider#registerConfig()` to create an empty `Config` object which can be filled manually via a builder. + This configuration instance *will* be shared by the `ConfigProvider`. + Any subsequent call to `ConfigProvider#getConfig()` will return the registered `Config` instance. + + +All methods in the `ConfigProvider` and `Config` implementations are thread safe and reentrant. + +If a `Config` is bound to an Application it is ensured that it gets properly removed if the Application gets destroyed. +The Config system deos not create any memory leaks in that case. + +A `Config` can be release manually by calling `ConfigProvider#release(Config)`. +ConfigSources which implement the `java.io.Closeable` interface will be properly destroyed. +Any subsequent call to `ConfigProvider#getConfig()` or `ConfigProvider#getConfig(ClassLoader forClassLoader)` will result in a new `Config` instance. + +<<< \ No newline at end of file diff --git a/spec/src/main/asciidoc/configsources.asciidoc b/spec/src/main/asciidoc/configsources.asciidoc index f7f562d..22e5d85 100644 --- a/spec/src/main/asciidoc/configsources.asciidoc +++ b/spec/src/main/asciidoc/configsources.asciidoc @@ -15,8 +15,8 @@ // limitations under the License. // -[[configsources]] -== ConfigSources +[[configsource]] +== ConfigSource A `ConfigSource` is exactly what its name says: a source for configured values. The `Config` uses all configured implementations of `ConfigSource` to look up the property in question. @@ -39,12 +39,15 @@ config_ordinal = 120 com.acme.myproject.someserver.url = http://more_important.server/some/endpoint ---- +[[default_configsources]] === Default ConfigSources A Microprofile-Config implementation must provide `ConfigSource` s for the following data out of the box: * System properties (ordinal=400) -* Environment properties (ordinal=300) +* Environment properties (ordinal=300). + The built in `ConfigSource` for the environment provides an all upper-case fallback lookup where dots are replaced with underlines. + An environment setting `ACME_MYKEY=bla` machtches a lookup for `config.getValue("acme.mykey")`. * A `ConfigSource` for each property file `META-INF/java-config.properties` found on the classpath. (default ordinal = 100) === Custom ConfigSources @@ -122,6 +125,8 @@ Please note that a single `ConfigSource` should be either registered directly or A `Config` instance provides no caching but iterates over all `ConfigSources` for each `getValue(String)` operation. A `ConfigSource` is allowed to cache the underlying values itself. +Users might use the `cacheFor(long, TimeUnit)` method of a `ConfigValue` to pick up values which might change at runtime without penetrating the configuration system. + === Manually adding ConfigSources @@ -129,3 +134,4 @@ A user can manually register `ConfigSource` s by using the method `void addConfi This will add the given list to the already registered `ConfigSources` of the current `Config` instance. The order in which the `ConfigSources` are evaluated when using `Config#getValue(String key)` is independent of the order in which they were added to the `Config`; this depends only on the `ordinal` values of the available `ConfigSources`. + diff --git a/spec/src/main/asciidoc/converters.asciidoc b/spec/src/main/asciidoc/converters.asciidoc index fc0a642..0131c39 100644 --- a/spec/src/main/asciidoc/converters.asciidoc +++ b/spec/src/main/asciidoc/converters.asciidoc @@ -15,8 +15,8 @@ // limitations under the License. // -[[converters]] -== Converters +[[converter]] +== Converter For providing typeseafe configuration we need to convert from the configured Strings into target types. This happens by providing `Converter` s in the `Config`. diff --git a/spec/src/main/asciidoc/license-alv2.asciidoc b/spec/src/main/asciidoc/license-alv2.asciidoc index ff9d5f6..276af0a 100644 --- a/spec/src/main/asciidoc/license-alv2.asciidoc +++ b/spec/src/main/asciidoc/license-alv2.asciidoc @@ -24,7 +24,7 @@ Version: {revnumber} Status: {revremark} -Specification Lead: Mark Struberg +Specification Lead: Mark Struberg, Emily Jiang Release: {revdate} diff --git a/spec/src/main/asciidoc/microprofile-config-spec.asciidoc b/spec/src/main/asciidoc/microprofile-config-spec.asciidoc index 187c9a5..eca5e96 100644 --- a/spec/src/main/asciidoc/microprofile-config-spec.asciidoc +++ b/spec/src/main/asciidoc/microprofile-config-spec.asciidoc @@ -37,6 +37,10 @@ include::license-alv2.asciidoc[] include::architecture.asciidoc[] +include::configexamples.asciidoc[] + +include::configprovider.asciidoc[] + include::configsources.asciidoc[] include::converters.asciidoc[] From bc854934f47f48efc2cc990da46e3270ad0ecb47 Mon Sep 17 00:00:00 2001 From: Mark Struberg Date: Tue, 17 Jan 2017 10:40:29 +0100 Subject: [PATCH 12/29] add missing () txs to rmannibucau for the report! --- spec/src/main/asciidoc/configexamples.asciidoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/src/main/asciidoc/configexamples.asciidoc b/spec/src/main/asciidoc/configexamples.asciidoc index ab1a817..3740cb1 100644 --- a/spec/src/main/asciidoc/configexamples.asciidoc +++ b/spec/src/main/asciidoc/configexamples.asciidoc @@ -60,13 +60,13 @@ For example if the configured values get picked up from a custom < public class DynamicConfigUsageSample { private ConfigValue urlConfigCfg - = ConfigProvider.getConfig.access("com.acme.myproject.someserver.url") + = ConfigProvider.getConfig().access("com.acme.myproject.someserver.url") .cacheFor(5, TimeUnit.MINUTES) .logChanges(true) .evaluateVariables(true); private ConfigValue urlPortCfg - = ConfigProvider.getConfig.access("com.acme.myproject.someserver.url") + = ConfigProvider.getConfig().access("com.acme.myproject.someserver.url") .as(Integer.class) .cacheFor(5, TimeUnit.MINUTES) .logChanges(true) From 210d6c7f49b2a0c96c5d5e2ed3fdd703f91273f8 Mon Sep 17 00:00:00 2001 From: Mark Struberg Date: Tue, 17 Jan 2017 11:55:55 +0100 Subject: [PATCH 13/29] add @Inject for Config and fix sample --- .../src/main/asciidoc/configexamples.asciidoc | 20 +++++++++++++------ .../src/main/asciidoc/configprovider.asciidoc | 8 ++++++-- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/spec/src/main/asciidoc/configexamples.asciidoc b/spec/src/main/asciidoc/configexamples.asciidoc index 3740cb1..4799e11 100644 --- a/spec/src/main/asciidoc/configexamples.asciidoc +++ b/spec/src/main/asciidoc/configexamples.asciidoc @@ -19,13 +19,13 @@ == Configuration Usage Examples An application can access it's configured values via a `Config` instance. -Use the `ConfigProvider` to access the `Config` of an application. +A user can use the `ConfigProvider` to access the `Config` of an application or simply use `@Inject Config` within CDI managed components. === Simple Example [source, java] ---- -public class ConfigUsageSample { +ppublic class ConfigUsageSample { public void useTheConfig() { // get access to the Config instance @@ -50,6 +50,7 @@ $> java -jar some.jar -Dcom.acme.myproject.someserver.url=http://other.server/ot Note that the way to inject this configuration into the application can be extended by providing custom `ConfigSource` s. + === Some advanced features It is also possible to dynamically pick up values which might change at runtime. @@ -57,21 +58,28 @@ For example if the configured values get picked up from a custom < [source, java] ---- +@ApplicationScoped public class DynamicConfigUsageSample { - private ConfigValue urlConfigCfg - = ConfigProvider.getConfig().access("com.acme.myproject.someserver.url") + private @Inject Config config; + + private ConfigValue serverUrlCfg; + private ConfigValue serverPortCfg + + @PostConstruct + private void init() { + serverUrlCfg= config.access("com.acme.myproject.someserver.url") .cacheFor(5, TimeUnit.MINUTES) .logChanges(true) .evaluateVariables(true); - private ConfigValue urlPortCfg - = ConfigProvider.getConfig().access("com.acme.myproject.someserver.url") + serverPortCfg = config.access("com.acme.myproject.someserver.port") .as(Integer.class) .cacheFor(5, TimeUnit.MINUTES) .logChanges(true) .evaluateVariables(true) .withDefault(8080); + } public void useTheConfig() { callToServer(serverUrlCfg.getValue(), serverPortCfg.getValue()); diff --git a/spec/src/main/asciidoc/configprovider.asciidoc b/spec/src/main/asciidoc/configprovider.asciidoc index 77c7285..ce39eb4 100644 --- a/spec/src/main/asciidoc/configprovider.asciidoc +++ b/spec/src/main/asciidoc/configprovider.asciidoc @@ -18,9 +18,13 @@ [[configprovider]] == Accessing or Creating a certain Configuration -The `ConfigProvider` is the central class to access a configuration. + +For manually accessing the `ConfigProvider` is the central class to access a configuration. It allows access to different configurations (represented by a `Config` instance) based on the application in which it is used. -We distinguish 3 different ways to resolve a `Config` instance: +We distinguish 5 different ways to create or `Config` instance: + +* In CDI manged components a user can use `@Inject` to access the current application configuration. + If no configuration is registered the automatic discovery of <> will be performed. * A factory method `ConfigProvider#getConfig()` to create a `Config` object based on automatically picked up `ConfigSources` of the Application identified by the current Thread Context ClassLoader classpath. From d322b3a35589bb73ec9bbe95e89be3f8341b1d88 Mon Sep 17 00:00:00 2001 From: Mark Struberg Date: Thu, 26 Jan 2017 08:40:50 +0100 Subject: [PATCH 14/29] add list handling --- api/pom.xml | 1 + .../main/java/io/microprofile/config/ConfigValue.java | 9 +++++++++ .../config/tck/configsources/SampleYamlConfigSource.java | 2 +- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/api/pom.xml b/api/pom.xml index 5a5765b..3a68c25 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -39,4 +39,5 @@ + diff --git a/api/src/main/java/io/microprofile/config/ConfigValue.java b/api/src/main/java/io/microprofile/config/ConfigValue.java index ddf0d91..d93b95b 100644 --- a/api/src/main/java/io/microprofile/config/ConfigValue.java +++ b/api/src/main/java/io/microprofile/config/ConfigValue.java @@ -103,6 +103,15 @@ public interface ConfigValue { */ T getValue(); + /** + * Resolves the value and split it on each comma (',') character. + * If a comma is contained in the values it must get escaped with a preceding backslash ("\,"). + * Any backslash needs to get escaped via double-backslash ("\\"). + * + * @return the list of configured comma separated values or an empty Iterable if no + */ + Iterable getValueList(); + /** * Returns the key given in {@link Config#access(String)}. * @return the original key diff --git a/tck/src/main/java/io/microprofile/config/tck/configsources/SampleYamlConfigSource.java b/tck/src/main/java/io/microprofile/config/tck/configsources/SampleYamlConfigSource.java index 4e7c4bb..1d64de5 100644 --- a/tck/src/main/java/io/microprofile/config/tck/configsources/SampleYamlConfigSource.java +++ b/tck/src/main/java/io/microprofile/config/tck/configsources/SampleYamlConfigSource.java @@ -34,7 +34,7 @@ public SampleYamlConfigSource(URL url) { @Override public int getOrdinal() { - return 110; + return config.get("ordinal") != null ? Integer.valueOf(config.get("ordinal")) : 110; } @Override From b8f480d11472d83603030ab765df424814d536cb Mon Sep 17 00:00:00 2001 From: Mark Struberg Date: Fri, 10 Mar 2017 00:14:04 +0100 Subject: [PATCH 15/29] adopt to microprofile API + fix a few things --- api/pom.xml | 43 ---- .../java/io/microprofile/config/Config.java | 87 -------- .../microprofile/config/ConfigProvider.java | 198 ------------------ .../io/microprofile/config/ConfigValue.java | 139 ------------ .../microprofile/config/spi/ConfigSource.java | 99 --------- .../config/spi/ConfigSourceProvider.java | 46 ---- .../io/microprofile/config/spi/Converter.java | 51 ----- impl/pom.xml | 12 +- .../apache/geronimo/config/ConfigImpl.java | 36 ++-- .../geronimo/config/ConfigValueImpl.java | 133 ++++++------ .../geronimo/config/DefaultConfigBuilder.java | 36 ++-- .../config/DefaultConfigProvider.java | 20 +- .../ManualApplicationConfigBuilder.java | 6 +- .../config/configsource/BaseConfigSource.java | 7 +- .../PropertyFileConfigSource.java | 6 +- .../PropertyFileConfigSourceProvider.java | 4 +- .../configsource/SystemEnvConfigSource.java | 6 +- .../SystemPropertyConfigSource.java | 6 +- .../config/converters/BooleanConverter.java | 2 +- .../config/converters/DoubleConverter.java | 2 +- .../config/converters/FloatConverter.java | 2 +- .../config/converters/IntegerConverter.java | 2 +- .../config/converters/LongConverter.java | 2 +- ...profile.config.spi.ConfigProviderResolver} | 0 impl/tck-suite.xml | 2 +- pom.xml | 7 +- spec/pom.xml | 98 --------- spec/src/main/asciidoc/architecture.asciidoc | 51 ----- .../src/main/asciidoc/configexamples.asciidoc | 92 -------- .../src/main/asciidoc/configprovider.asciidoc | 57 ----- spec/src/main/asciidoc/configsources.asciidoc | 137 ------------ spec/src/main/asciidoc/converters.asciidoc | 48 ----- spec/src/main/asciidoc/license-alv2.asciidoc | 44 ---- .../microprofile-config-spec.asciidoc | 46 ---- tck/pom.xml | 55 ----- .../config/tck/ConfigProviderTest.java | 148 ------------- .../config/tck/ConfigSourceProviderTest.java | 35 ---- .../config/tck/ConfigValueTest.java | 132 ------------ .../config/tck/ConverterTest.java | 46 ---- .../config/tck/CustomConfigSourceTest.java | 35 ---- .../CustomConfigSourceProvider.java | 47 ----- .../configsources/CustomDbConfigSource.java | 63 ------ .../configsources/SampleYamlConfigSource.java | 55 ----- .../config/tck/converters/Duck.java | 33 --- .../config/tck/converters/DuckConverter.java | 30 --- .../resources/META-INF/java-config.properties | 73 ------- .../io.microprofile.config.spi.ConfigSource | 20 -- ...croprofile.config.spi.ConfigSourceProvider | 20 -- tck/src/main/resources/sampleconfig.yaml | 20 -- 49 files changed, 151 insertions(+), 2188 deletions(-) delete mode 100644 api/pom.xml delete mode 100644 api/src/main/java/io/microprofile/config/Config.java delete mode 100644 api/src/main/java/io/microprofile/config/ConfigProvider.java delete mode 100644 api/src/main/java/io/microprofile/config/ConfigValue.java delete mode 100644 api/src/main/java/io/microprofile/config/spi/ConfigSource.java delete mode 100644 api/src/main/java/io/microprofile/config/spi/ConfigSourceProvider.java delete mode 100644 api/src/main/java/io/microprofile/config/spi/Converter.java rename impl/src/main/resources/META-INF/services/{io.microprofile.config.ConfigProvider$SPI => org.eclipse.microprofile.config.spi.ConfigProviderResolver} (100%) delete mode 100644 spec/pom.xml delete mode 100644 spec/src/main/asciidoc/architecture.asciidoc delete mode 100644 spec/src/main/asciidoc/configexamples.asciidoc delete mode 100644 spec/src/main/asciidoc/configprovider.asciidoc delete mode 100644 spec/src/main/asciidoc/configsources.asciidoc delete mode 100644 spec/src/main/asciidoc/converters.asciidoc delete mode 100644 spec/src/main/asciidoc/license-alv2.asciidoc delete mode 100644 spec/src/main/asciidoc/microprofile-config-spec.asciidoc delete mode 100644 tck/pom.xml delete mode 100644 tck/src/main/java/io/microprofile/config/tck/ConfigProviderTest.java delete mode 100644 tck/src/main/java/io/microprofile/config/tck/ConfigSourceProviderTest.java delete mode 100644 tck/src/main/java/io/microprofile/config/tck/ConfigValueTest.java delete mode 100644 tck/src/main/java/io/microprofile/config/tck/ConverterTest.java delete mode 100644 tck/src/main/java/io/microprofile/config/tck/CustomConfigSourceTest.java delete mode 100644 tck/src/main/java/io/microprofile/config/tck/configsources/CustomConfigSourceProvider.java delete mode 100644 tck/src/main/java/io/microprofile/config/tck/configsources/CustomDbConfigSource.java delete mode 100644 tck/src/main/java/io/microprofile/config/tck/configsources/SampleYamlConfigSource.java delete mode 100644 tck/src/main/java/io/microprofile/config/tck/converters/Duck.java delete mode 100644 tck/src/main/java/io/microprofile/config/tck/converters/DuckConverter.java delete mode 100644 tck/src/main/resources/META-INF/java-config.properties delete mode 100644 tck/src/main/resources/META-INF/services/io.microprofile.config.spi.ConfigSource delete mode 100644 tck/src/main/resources/META-INF/services/io.microprofile.config.spi.ConfigSourceProvider delete mode 100644 tck/src/main/resources/sampleconfig.yaml diff --git a/api/pom.xml b/api/pom.xml deleted file mode 100644 index 3a68c25..0000000 --- a/api/pom.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - 4.0.0 - - - - org.apache.geronimo.config - config-parent - 0.1-SNAPSHOT - - - org.apache.geronimo.config - config-api - - - - Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt - repo - A business-friendly OSS license - - - - - diff --git a/api/src/main/java/io/microprofile/config/Config.java b/api/src/main/java/io/microprofile/config/Config.java deleted file mode 100644 index 76e2e55..0000000 --- a/api/src/main/java/io/microprofile/config/Config.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * See the NOTICE file distributed with this work for additional information - * regarding copyright ownership. - * The author 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 io.microprofile.config; - -import java.util.Map; - -import io.microprofile.config.spi.ConfigSourceProvider; -import io.microprofile.config.spi.Converter; -import io.microprofile.config.spi.ConfigSource; - -/** - *

Resolves configured values of properties by going through the list - * of configured {@link ConfigSource}s and using the one with the highest ordinal. - * If multiple {@link ConfigSource}s have the same ordinal, their order is undefined.

- * - *

You can provide your own lookup paths by implementing and registering additional - * {@link ConfigSource}s and {@link ConfigSourceProvider} implementations.

- * - * - * @see ConfigProvider to resolve the current configuration. - * - * @author Mark Struberg - */ -public interface Config { - - /** - * Create a {@link ConfigValue} to access the underlying configuration. - * - * @param key the property key - */ - ConfigValue access(String key); - - /** - * Resolves the value configured for the given key. - * - * @param key the property key - * - * @return the configured property value from the {@link ConfigSource} with the highest ordinal - * or {@code null} if there is no configured value for it - */ - String getValue(String key); - - /** - * Resolves the value configured for the given key and convert it to the required asType. - * - * @param key - * @param asType Also support parameterized Types? - * @param - * @return - * @throws UnsupportedOperationException if there is no {@link Converter} registered for asType - */ - T getValue(String key, Class asType); - - /** - * Apply the - * @return the String converted - * @throws UnsupportedOperationException if there is no {@link Converter} registered for asType - */ - T convert(String value, Class asType); - - /** - * Returns a Map of all properties from all scannable config sources. The values of the properties reflect the - * values that would be obtained by a call to {@link #getValue(java.lang.String)}, that is, the value of the - * property from the ConfigSource with the highest ordinal. - */ - Map getAllProperties(); - - /** - * @return all currently registered {@link ConfigSource}s - */ - ConfigSource[] getConfigSources(); - -} diff --git a/api/src/main/java/io/microprofile/config/ConfigProvider.java b/api/src/main/java/io/microprofile/config/ConfigProvider.java deleted file mode 100644 index ae0f690..0000000 --- a/api/src/main/java/io/microprofile/config/ConfigProvider.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * See the NOTICE file distributed with this work for additional information - * regarding copyright ownership. - * The author 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 io.microprofile.config; - -import java.util.ServiceLoader; -import java.util.logging.Logger; - -import io.microprofile.config.spi.ConfigSource; -import io.microprofile.config.spi.Converter; - -/** - *

This is the central class to access a {@link Config}.

- * - *

A {@link Config} contains the configuration for a certain - * situation. That might be the configuration found in a certain ClassLoader - * or even a manually created Configuration

- * - *

The default usage is to use {@link #getConfig()} to automatically - * pick up the 'Configuration' for the Thread Context ClassLoader - * (See {@link Thread#getContextClassLoader()}).

- * - *

A 'Configuration' consists of the information collected from the registered - * {@link ConfigSource}s. These {@link ConfigSource}s - * get sorted according to their ordinal defined via {@link ConfigSource#getOrdinal()}. - * That way it is possible to overwrite configuration with lower importance from outside.

- * - *

It is also possible to register custom {@link ConfigSource}s to - * flexibly extend the configuration mechanism. An example would be to pick up configuration values - * from a database table./p> - * - *

Example usage: - * - *

- *     String restUrl = ConfigProvider.getConfig().getValue("myproject.some.remote.service.url");
- *     Integer port = ConfigProvider.getConfig().getValue("myproject.some.remote.service.port", Integer.class);
- * 
- * - *

- * - * @author Mark Struberg - * @author Romain Manni-Bucau - */ -public class ConfigProvider { - - private static volatile SPI instance; - - /** - * Provide a {@link Config} based on all {@link ConfigSource}s - * of the current Thread Context ClassLoader (TCCL) - * - *

There is exactly a single Config instance per Application

- */ - public static Config getConfig() { - return loadSpi().getConfig(); - } - - /** - * Provide a {@link Config} based on all {@link ConfigSource}s - * of the given ClassLoader. - * - *

There is exactly a single Config instance per Application. The Application get's identified via a ClassLoader

- */ - public static Config getConfig(ClassLoader forClassLoader) { - return instance.getConfig(forClassLoader); - } - - /** - * Create a {@link ConfigBuilder} for providing a fresh {@link Config} instance. - * - * The ConfigProvider will not manage the Config instance internally. - * That means that {@link #getConfig()} does not pick up a Config created that way. - */ - public static ConfigBuilder newConfig() { - return instance.newConfig(); - } - - /** - * Create a {@link ConfigBuilder} for register a {@link Config} instance to a certain Application. - * Invoking {@link ConfigBuilder#build()} will effectively register the Config. - * Use {@link ConfigBuilder#forClassLoader(ClassLoader)} to define the application the Config should be for, - * otherwise the current ThreadContextClassLoader will be used. - * - * A {@link Config} registered that way will get picked up on any subsequent call to {@link ConfigProvider#getConfig()}. - * - * @throws IllegalStateException if a {@link Config} has already been associated for the Application. - */ - public static ConfigBuilder registerConfig() { - return instance.registerConfig(); - } - - - /** - * A {@link Config} normally gets released if the ClassLoader it represents gets destroyed. - * Invoke this method if you like to destroy the Config prematurely. - */ - public static void releaseConfig(Config config) { - instance.releaseConfig(config); - } - - - /** - * Builder for manually creating an instance of a {@code Config}. - * - * @see ConfigProvider#newConfig() - */ - public interface ConfigBuilder { - ConfigBuilder ignoreDefaultSources(); - ConfigBuilder forClassLoader(ClassLoader loader); - ConfigBuilder withSources(ConfigSource... sources); - ConfigBuilder withConverters(Converter... filters); - Config build(); - } - - /** - * This interface gets implemented internally by the Config library. - * The implementation registers itself via {@link java.util.ServiceLoader} mechanism. - * In an OSGi environment - */ - public interface SPI { - Config getConfig(); - Config getConfig(ClassLoader forClassLoader); - ConfigBuilder newConfig(); - ConfigBuilder registerConfig(); - void releaseConfig(Config config); - } - - /** - * Attention, handle with care! - * This method is not intended to be used from a user. - * It is for integration with e.g. OSGi from within a BundleActivator. - * TODO probably remove this and add native OSGi support later. - */ - public static synchronized void setSPI(SPI newInstance) { - instance = newInstance; - } - - private static SPI loadSpi() { - if (instance == null) { - synchronized (SPI.class) { - if (instance != null) { - return instance; - } - ClassLoader cl = Thread.currentThread().getContextClassLoader(); - if (cl == null) { - cl = SPI.class.getClassLoader(); - } - - SPI newInstance = loadSpi(cl); - - if (newInstance == null) { - throw new IllegalStateException("No ConfigResolver SPI implementation found!"); - } - - instance = newInstance; - } - } - - return instance; - } - - private static SPI loadSpi(ClassLoader cl) { - if (cl == null) { - return null; - } - - // start from the root CL and go back down to the TCCL - SPI instance = loadSpi(cl.getParent()); - - if (instance == null) { - ServiceLoader sl = ServiceLoader.load(SPI.class, cl); - for (SPI spi : sl) { - if (instance != null) { - Logger.getLogger(ConfigProvider.class.getName()) - .warning("Multiple ConfigResolver SPIs found. Ignoring " + spi.getClass().getName()); - } else { - instance = spi; - } - } - } - return instance; - } - - -} diff --git a/api/src/main/java/io/microprofile/config/ConfigValue.java b/api/src/main/java/io/microprofile/config/ConfigValue.java deleted file mode 100644 index d93b95b..0000000 --- a/api/src/main/java/io/microprofile/config/ConfigValue.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * See the NOTICE file distributed with this work for additional information - * regarding copyright ownership. - * The author 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 io.microprofile.config; - - -import java.util.concurrent.TimeUnit; - -/** - * Accessor to a configured value. - * It follows a builder pattern. - * - * Accessing the configured value is finally done via {@link #getValue()} - * - * @author Mark Struberg - * @author Gerhard Petracek - * @author Ron Smeral - */ -public interface ConfigValue { - - /** - * Sets the type of the configuration entry to the given class and returns this builder. - * The default type of a ConfigValue is {@code String}. - * - * @param clazz The target type - * @param The target type - * @return This builder as a typed ConfigValue - */ - ConfigValue as(Class clazz); - - /** - * Sets the default value to use in case the resolution returns null. - * @param value the default value - * @return This builder - */ - ConfigValue withDefault(T value); - - /** - * Sets the default value to use in case the resolution returns null. Converts the given String to the type of - * this resolver using the same method as used for the configuration entries. - * @param value string value to be converted and used as default - * @return This builder - */ - ConfigValue withStringDefault(String value); - - /** - * Specify that a resolved value will get cached for a certain amount of time. - * After the time expires the next {@link #getValue()} will again resolve the value - * from the underlying {@link Config}. - * - * @param value the amount of the TimeUnit to wait - * @param timeUnit the TimeUnit for the value - * - * @return This builder - */ - ConfigValue cacheFor(long value, TimeUnit timeUnit); - - /** - * Whether to evaluate variables in configured values. - * A variable starts with '${' and ends with '}', e.g. - *
-     * mycompany.some.url=${myserver.host}/some/path
-     * myserver.host=http://localhost:8081
-     * 
- * If 'evaluateVariables' is enabled, the result for the above key - * {@code "mycompany.some.url"} would be: - * {@code "http://localhost:8081/some/path"} - * @param evaluateVariables whether to evaluate variables in values or not - * @return This builder - */ - ConfigValue evaluateVariables(boolean evaluateVariables); - - /** - * Appends the resolved value of the given property to the key of this builder. - * TODO further explain. - * @return This builder - */ - ConfigValue withLookupChain(String... postfixNames); - - /** - * Whether to log picking up any value changes as INFO. - * - * @return This builder - */ - ConfigValue logChanges(boolean logChanges); - - /** - * Returns the converted resolved filtered value. - * @return the resolved value - */ - T getValue(); - - /** - * Resolves the value and split it on each comma (',') character. - * If a comma is contained in the values it must get escaped with a preceding backslash ("\,"). - * Any backslash needs to get escaped via double-backslash ("\\"). - * - * @return the list of configured comma separated values or an empty Iterable if no - */ - Iterable getValueList(); - - /** - * Returns the key given in {@link Config#access(String)}. - * @return the original key - */ - String getKey(); - - /** - * Returns the actual key which led to successful resolution and corresponds to the resolved value. This applies - * only when {@link #withLookupChain(String...)} is used. - * Otherwise the resolved key should always be equal to the original key. - * This method is provided for cases, when arameterized resolution is - * requested but the value for such appended key is not found and some of the fallback keys is used. - * - * This should be called only after calling {@link #getValue()} otherwise the value is undefined (but likely - * null). - */ - String getResolvedKey(); - - /** - * Returns the default value provided by {@link #withDefault(Object)} or {@link #withStringDefault(String)}. - * Returns null if no default was provided. - * @return the default value or {@code null} - */ - T getDefaultValue(); -} diff --git a/api/src/main/java/io/microprofile/config/spi/ConfigSource.java b/api/src/main/java/io/microprofile/config/spi/ConfigSource.java deleted file mode 100644 index 6340aea..0000000 --- a/api/src/main/java/io/microprofile/config/spi/ConfigSource.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * See the NOTICE file distributed with this work for additional information - * regarding copyright ownership. - * The author 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 io.microprofile.config.spi; - -import java.util.Map; - -/** - *

Implement this interfaces to provide a ConfigSource. - * A ConfigSource provides properties from a specific place, like - * JNDI configuration, a properties file, etc. - * A ConfigSource is always read-only, any potential updates of the - * configured values must be handled directly inside each ConfigSource.

- * - *

The custom implementation can be 'registered' using a - * {@link ConfigSourceProvider} or via the - * {@link java.util.ServiceLoader} mechanism. In the later case - * it must get registered via creating a - * META-INF/services/javax.config.spi.ConfigSource - * file and adding the fully qualified class name of your ConfigSource - * implementation into it.

- * - * @author Mark Struberg - * @author Gerhard Petracek - */ -public interface ConfigSource { - /** - * The default name for the ordinal field. - * Any ConfigSource might use it's own though or even return a hardcoded - * in {@link #getOrdinal()}. - */ - String CONFIG_ORDINAL = "config_ordinal"; - - - /** - * Lookup order: - * - *
    - *
  1. System properties (ordinal 400)
  2. - *
  3. Environment properties (ordinal 300)
  4. - *
  5. JNDI values (ordinal 200)
  6. - *
  7. Properties file values (/META-INF/java-config.properties) (ordinal 100)
  8. - *
- *

- *

Important Hints for custom implementations:

- *

- * If a custom implementation should be invoked before the default implementations, use a value > 400 - *

- *

- * If a custom implementation should be invoked after the default implementations, use a value < 100 - *

- *

- * - * - *

- *

- *

Reordering of the default order of the config-sources:

- *

Example: If the properties file/s should be used before the other implementations, - * you have to configure an ordinal > 400. That means, you have to add e.g. config_ordinal=401 to - * /META-INF/java-config.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.

- * - * @return the 'importance' aka ordinal of the configured values. The higher, the more important. - */ - int getOrdinal(); - - /** - * Return properties contained in this config source. - * @return Properties available in this config source. - */ - Map getProperties(); - - /** - * @param key for the property - * @return configured value or null if this ConfigSource doesn't provide any value for the given key. - */ - String getPropertyValue(String key); - - /** - * The name of the config might be used for logging or analysis of configured values. - * - * @return the 'name' of the configuration source, e.g. 'property-file mylocation/myproperty.properties' - */ - String getConfigName(); - -} diff --git a/api/src/main/java/io/microprofile/config/spi/ConfigSourceProvider.java b/api/src/main/java/io/microprofile/config/spi/ConfigSourceProvider.java deleted file mode 100644 index ca4e04c..0000000 --- a/api/src/main/java/io/microprofile/config/spi/ConfigSourceProvider.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * See the NOTICE file distributed with this work for additional information - * regarding copyright ownership. - * The author 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 io.microprofile.config.spi; - -import java.util.List; - -/** - *

Implement this interfaces to provide a ConfigSource provider which - * is able to maintain multiple ConfigSources. This is e.g. needed if - * there are multiple property files of a given name.

- * - *

If a ConfigSource like JNDI only exists once, then there is no need - * to implement it via the ConfigSourceProvider but should directly - * expose a {@link ConfigSource}.

- * - *

A ConfigSourceProvider will get picked up via the - * {@link java.util.ServiceLoader} mechanism and must get registered via - * META-INF/services/javax.config.spi.ConfigSourceProvider

- * - * @author Mark Struberg - */ -public interface ConfigSourceProvider -{ - - /** - * @param forClassLoader the classloader which should be used if any is needed - * - * @return For each e.g. property file, we return a single ConfigSource or an empty list if no ConfigSource exists. - */ - List getConfigSources(ClassLoader forClassLoader); -} diff --git a/api/src/main/java/io/microprofile/config/spi/Converter.java b/api/src/main/java/io/microprofile/config/spi/Converter.java deleted file mode 100644 index b6565b5..0000000 --- a/api/src/main/java/io/microprofile/config/spi/Converter.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * See the NOTICE file distributed with this work for additional information - * regarding copyright ownership. - * The author 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 io.microprofile.config.spi; - -/** - *

A very simple interface for conversion of configuration values from String to any Java type.

- * - *

A Converter can specify a {@link javax.annotation.Priority}. - * If no priority is explicitly assigned, the value of 100 is assumed.

- * - *

If multiple Converter get found the one with the highest priority will be used.

- * - *

The Converter for the following types are automatically enabled: - *

    - *
  • Boolean, values for {@code true}: (case insensitive) "true", "1", "YES", "Y" "JA" "J", "OUI"
  • - *
  • Integer
  • - *
  • Long
  • - *
  • Float, a dot '.' is used to separate the fractional digits
  • - *
  • Double, a dot '.' is used to separate the fractional digits - *
- * - *

- * - * @author Mark Struberg - * @author Ron Smeral - * @author Gerhard Petracek - */ -public interface Converter { - /** - * Returns the converted value of the configuration entry. - * @param value The String property value to convert - * @return Converted value - */ - T convert(String value); - -} diff --git a/impl/pom.xml b/impl/pom.xml index 69d8a7c..618a423 100644 --- a/impl/pom.xml +++ b/impl/pom.xml @@ -32,15 +32,15 @@ - org.apache.geronimo.config - config-api - 0.1-SNAPSHOT + org.eclipse.microprofile.config.api + microprofile-config-api + 1.0-SNAPSHOT - org.apache.geronimo.config - config-tck - 0.1-SNAPSHOT + org.eclipse.microprofile.config.tck + microprofile-config-tck + 1.0-SNAPSHOT test diff --git a/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java b/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java index a9feb00..89bf067 100644 --- a/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java +++ b/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java @@ -23,15 +23,18 @@ import java.util.Collections; import java.util.Comparator; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Optional; +import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; -import io.microprofile.config.Config; -import io.microprofile.config.ConfigValue; -import io.microprofile.config.spi.ConfigSource; -import io.microprofile.config.spi.Converter; +import org.eclipse.microprofile.config.Config; +import org.eclipse.microprofile.config.ConfigValue; +import org.eclipse.microprofile.config.spi.ConfigSource; +import org.eclipse.microprofile.config.spi.Converter; import org.apache.geronimo.config.converters.BooleanConverter; import org.apache.geronimo.config.converters.DoubleConverter; import org.apache.geronimo.config.converters.FloatConverter; @@ -63,14 +66,18 @@ private void registerDefaultConverter() { } @Override + public Optional getString(String key) { + return Optional.ofNullable(getValue(key)); + } + public String getValue(String key) { for (ConfigSource configSource : configSources) { - String value = configSource.getPropertyValue(key); + String value = configSource.getValue(key); if (value != null) { if (logger.isLoggable(Level.FINE)) { logger.log(Level.FINE, "found value {0} for key {1} in ConfigSource {2}.", - new Object[]{value, key, configSource.getConfigName()}); + new Object[]{value, key, configSource.getName()}); } return value; @@ -80,12 +87,11 @@ public String getValue(String key) { } @Override - public T getValue(String key, Class asType) { + public Optional getValue(String key, Class asType) { String value = getValue(key); - return convert(value, asType); + return Optional.ofNullable(convert(value, asType)); } - @Override public T convert(String value, Class asType) { Converter converter = getConverter(asType); if (value != null) { @@ -104,22 +110,22 @@ private Converter getConverter(Class asType) { } public ConfigValue access(String key) { - return new ConfigValueImpl<>(this, key); + return new ConfigValueImpl(this, key); } @Override - public Map getAllProperties() { - Map result = new HashMap(); + public Iterable getPropertyNames() { + Set result = new HashSet<>(); for (int i = configSources.length; i > 0; i--) { ConfigSource configSource = configSources[i]; - result.putAll(configSource.getProperties()); + result.addAll(configSource.getProperties().keySet()); } - - return Collections.unmodifiableMap(result); + return result; } + @Override public ConfigSource[] getConfigSources() { return configSources; diff --git a/impl/src/main/java/org/apache/geronimo/config/ConfigValueImpl.java b/impl/src/main/java/org/apache/geronimo/config/ConfigValueImpl.java index b552493..90f8884 100644 --- a/impl/src/main/java/org/apache/geronimo/config/ConfigValueImpl.java +++ b/impl/src/main/java/org/apache/geronimo/config/ConfigValueImpl.java @@ -16,17 +16,20 @@ */ package org.apache.geronimo.config; -import io.microprofile.config.ConfigValue; -import io.microprofile.config.spi.Converter; +import org.eclipse.microprofile.config.ConfigValue; +import org.eclipse.microprofile.config.spi.Converter; +import java.util.ArrayList; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Optional; import java.util.concurrent.TimeUnit; -import java.util.logging.Level; import java.util.logging.Logger; /** * @author Mark Struberg */ -public class ConfigValueImpl implements ConfigValue { +public class ConfigValueImpl implements ConfigValue { private static final Logger logger = Logger.getLogger(ConfigValueImpl.class.getName()); private final ConfigImpl config; @@ -39,19 +42,12 @@ public class ConfigValueImpl implements ConfigValue { private String[] lookupChain; - private boolean withDefault = false; - private T defaultValue; - - - private Converter converter; - private boolean evaluateVariables = false; - private boolean logChanges = false; - private long cacheTimeMs = -1; private volatile long reloadAfter = -1; private T lastValue = null; + private ConfigChanged valueChangeListener; public ConfigValueImpl(ConfigImpl config, String key) { this.config = config; @@ -61,29 +57,9 @@ public ConfigValueImpl(ConfigImpl config, String key) { @Override public ConfigValue as(Class clazz) { configEntryType = clazz; - this.converter = null; return (ConfigValue) this; } - @Override - public ConfigValue withDefault(T value) { - defaultValue = value; - withDefault = true; - return this; - } - - @Override - public ConfigValue withStringDefault(String value) { - if (value == null || value.isEmpty()) - { - throw new RuntimeException("Empty String or null supplied as string-default value for property " - + keyOriginal); - } - - defaultValue = convert(value); - withDefault = true; - return this; - } @Override public ConfigValue cacheFor(long value, TimeUnit timeUnit) { @@ -97,20 +73,76 @@ public ConfigValue evaluateVariables(boolean evaluateVariables) { return this; } - @Override public ConfigValue withLookupChain(String... postfixNames) { this.lookupChain = postfixNames; return this; } @Override - public ConfigValue logChanges(boolean logChanges) { - this.logChanges = logChanges; + public T get() { + T val = getValue(); + if (val == null) { + throw new NoSuchElementException("No config value present for key " + keyOriginal); + } + return val; + } + + @Override + public Optional getOptional() { + return Optional.ofNullable(getValue()); + } + + @Override + public ConfigValue onChange(ConfigChanged valueChangeListener) { + this.valueChangeListener = valueChangeListener; return this; } @Override + public List getValueList() { + String rawList = (String) getValue(false); + List values = new ArrayList(); + StringBuilder sb = new StringBuilder(64); + for (int i= 0; i < rawList.length(); i++) { + char c = rawList.charAt(i); + if ('\\' == c) { + if (i == rawList.length()) { + throw new IllegalStateException("incorrect escaping of key " + keyOriginal + " value: " + rawList); + } + char nextChar = rawList.charAt(i+1); + if (nextChar == '\\') { + sb.append('\\'); + } + else if (nextChar == ',') { + sb.append(','); + } + i++; + } + else if (',' == c) { + addListValue(values, sb); + } + else { + sb.append(c); + } + } + addListValue(values, sb); + + return values; + } + + private void addListValue(List values, StringBuilder sb) { + String val = sb.toString().trim(); + if (!val.isEmpty()) { + values.add(convert(val)); + } + sb.setLength(0); + } + public T getValue() { + return getValue(true); + } + + private T getValue(boolean convert) { long now = -1; if (cacheTimeMs > 0) { @@ -122,17 +154,11 @@ public T getValue() { } String valueStr = resolveStringValue(); - T value = convert(valueStr); + T value = convert ? convert(valueStr) : (T) valueStr; - if (withDefault) + if (valueChangeListener != null && (value != null && !value.equals(lastValue) || (value == null && lastValue != null)) ) { - value = fallbackToDefaultIfEmpty(keyResolved, value, defaultValue); - } - - if (logChanges && (value != null && !value.equals(lastValue) || (value == null && lastValue != null)) ) - { - logger.log(Level.INFO, "New value {0} for key {1}.", - new Object[]{valueStr, keyOriginal}); + valueChangeListener.onValueChange(keyOriginal, lastValue, value); } lastValue = value; @@ -165,7 +191,7 @@ private String resolveStringValue() { { break; } - String variableValue = config.access(varName).evaluateVariables(true).withLookupChain(lookupChain).getValue(); + String variableValue = config.access(varName).evaluateVariables(true).get(); if (variableValue != null) { value = value.replace("${" + varName + "}", variableValue); @@ -186,11 +212,6 @@ public String getResolvedKey() { return keyResolved; } - @Override - public T getDefaultValue() { - return defaultValue; - } - private T convert(String value) { if (String.class == configEntryType) { return (T) value; @@ -204,16 +225,4 @@ private T convert(String value) { return (T) converter.convert(value); } - private T fallbackToDefaultIfEmpty(String key, T value, T defaultValue) { - if (value == null || (value instanceof String && ((String)value).isEmpty())) - { - logger.log(Level.FINE, "no configured value found for key {0}, using default value {1}.", - new Object[]{key, defaultValue}); - - return defaultValue; - } - - return value; - } - } diff --git a/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java b/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java index 2d504d3..49fbad0 100644 --- a/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java +++ b/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java @@ -16,11 +16,11 @@ */ package org.apache.geronimo.config; -import io.microprofile.config.Config; -import io.microprofile.config.ConfigProvider; -import io.microprofile.config.spi.ConfigSource; -import io.microprofile.config.spi.ConfigSourceProvider; -import io.microprofile.config.spi.Converter; +import org.eclipse.microprofile.config.Config; +import org.eclipse.microprofile.config.spi.ConfigBuilder; +import org.eclipse.microprofile.config.spi.ConfigSource; +import org.eclipse.microprofile.config.spi.ConfigSourceProvider; +import org.eclipse.microprofile.config.spi.Converter; import org.apache.geronimo.config.configsource.PropertyFileConfigSourceProvider; import org.apache.geronimo.config.configsource.SystemEnvConfigSource; import org.apache.geronimo.config.configsource.SystemPropertyConfigSource; @@ -36,32 +36,32 @@ * @author Romain Manni-Bucau * @author Mark Struberg */ -public class DefaultConfigBuilder implements ConfigProvider.ConfigBuilder { +public class DefaultConfigBuilder implements ConfigBuilder { protected ClassLoader forClassLoader; private final List sources = new ArrayList<>(); private final List> converters = new ArrayList<>(); - private boolean ignoreDefaultSources = false; + private boolean ignoreDefaultSources = true; @Override - public ConfigProvider.ConfigBuilder ignoreDefaultSources() { - this.ignoreDefaultSources = true; + public ConfigBuilder addDefaultSources() { + this.ignoreDefaultSources = false; return this; } @Override - public ConfigProvider.ConfigBuilder forClassLoader(final ClassLoader loader) { + public ConfigBuilder forClassLoader(final ClassLoader loader) { this.forClassLoader = loader; return this; } @Override - public ConfigProvider.ConfigBuilder withSources(final ConfigSource... sources) { + public ConfigBuilder withSources(final ConfigSource... sources) { this.sources.addAll(asList(sources)); return this; } @Override - public ConfigProvider.ConfigBuilder withConverters(Converter... converters) { + public ConfigBuilder withConverters(Converter... converters) { this.converters.addAll(asList(converters)); return this; } @@ -78,15 +78,13 @@ public Config build() { if (!ignoreDefaultSources) { // load all ConfigSource services ServiceLoader configSourceLoader = ServiceLoader.load(ConfigSource.class, forClassLoader); - for (ConfigSource configSource : configSourceLoader) { - configSources.add(configSource); - } + configSourceLoader.forEach(configSource -> configSources.add(configSource)); // load all ConfigSources from ConfigSourceProviders ServiceLoader configSourceProviderLoader = ServiceLoader.load(ConfigSourceProvider.class, forClassLoader); - for (ConfigSourceProvider configSourceProvider : configSourceProviderLoader) { - configSources.addAll(configSourceProvider.getConfigSources(forClassLoader)); - } + configSourceProviderLoader.forEach(configSourceProvider -> + configSourceProvider.getConfigSources(forClassLoader) + .forEach(configSource -> configSources.add(configSource))); } ConfigImpl config = new ConfigImpl(); @@ -104,7 +102,7 @@ protected Collection getBuiltInConfigSources(ClassLoader configSources.add(new SystemEnvConfigSource()); configSources.add(new SystemPropertyConfigSource()); - configSources.addAll(new PropertyFileConfigSourceProvider("META-INF/java-config.properties", true, forClassLoader).getConfigSources(forClassLoader)); + configSources.addAll(new PropertyFileConfigSourceProvider("META-INF/microprofile-config.properties", true, forClassLoader).getConfigSources(forClassLoader)); return configSources; } diff --git a/impl/src/main/java/org/apache/geronimo/config/DefaultConfigProvider.java b/impl/src/main/java/org/apache/geronimo/config/DefaultConfigProvider.java index 03adbff..0d280ed 100644 --- a/impl/src/main/java/org/apache/geronimo/config/DefaultConfigProvider.java +++ b/impl/src/main/java/org/apache/geronimo/config/DefaultConfigProvider.java @@ -21,16 +21,17 @@ import java.util.Iterator; import java.util.Map; import java.util.WeakHashMap; -import io.microprofile.config.Config; -import io.microprofile.config.ConfigProvider; +import org.eclipse.microprofile.config.Config; +import org.eclipse.microprofile.config.spi.ConfigBuilder; +import org.eclipse.microprofile.config.spi.ConfigProviderResolver; /** * @author Mark Struberg */ -public class DefaultConfigProvider implements ConfigProvider.SPI { +public class DefaultConfigProvider extends ConfigProviderResolver { - protected static Map> configs + private static Map> configs = Collections.synchronizedMap(new WeakHashMap>()); @@ -51,7 +52,7 @@ public Config getConfig(ClassLoader forClassLoader) { synchronized (DefaultConfigProvider.class) { config = existingConfig(forClassLoader); if (config == null) { - config = createConfig(forClassLoader); + config = getBuilder().forClassLoader(forClassLoader).addDefaultSources().build(); registerConfig(config, forClassLoader); } } @@ -64,9 +65,6 @@ Config existingConfig(ClassLoader forClassLoader) { return configRef != null ? configRef.get() : null; } - protected Config createConfig(ClassLoader forClassLoader) { - return newConfig().forClassLoader(forClassLoader).build(); - } void registerConfig(Config config, ClassLoader forClassLoader) { synchronized (DefaultConfigProvider.class) { @@ -75,13 +73,13 @@ void registerConfig(Config config, ClassLoader forClassLoader) { } @Override - public ConfigProvider.ConfigBuilder newConfig() { + public ConfigBuilder getBuilder() { return new DefaultConfigBuilder(); } @Override - public ConfigProvider.ConfigBuilder registerConfig() { - return new ManualApplicationConfigBuilder(this); + public void setConfig(Config config, ClassLoader classLoader) { + registerConfig(config, classLoader); } @Override diff --git a/impl/src/main/java/org/apache/geronimo/config/ManualApplicationConfigBuilder.java b/impl/src/main/java/org/apache/geronimo/config/ManualApplicationConfigBuilder.java index 9b91edf..01ee075 100644 --- a/impl/src/main/java/org/apache/geronimo/config/ManualApplicationConfigBuilder.java +++ b/impl/src/main/java/org/apache/geronimo/config/ManualApplicationConfigBuilder.java @@ -16,8 +16,8 @@ */ package org.apache.geronimo.config; -import io.microprofile.config.Config; -import io.microprofile.config.ConfigProvider; +import org.eclipse.microprofile.config.Config; +import org.eclipse.microprofile.config.spi.ConfigProviderResolver; /** * @author Mark Struberg @@ -36,7 +36,7 @@ public synchronized Config build() { if (cl == null) { cl = Thread.currentThread().getContextClassLoader(); if (cl == null) { - cl = ConfigProvider.SPI.class.getClassLoader(); + cl = ConfigProviderResolver.class.getClassLoader(); } } Config oldConfig = configProvider.existingConfig(cl); diff --git a/impl/src/main/java/org/apache/geronimo/config/configsource/BaseConfigSource.java b/impl/src/main/java/org/apache/geronimo/config/configsource/BaseConfigSource.java index 9ffbc10..d7117be 100644 --- a/impl/src/main/java/org/apache/geronimo/config/configsource/BaseConfigSource.java +++ b/impl/src/main/java/org/apache/geronimo/config/configsource/BaseConfigSource.java @@ -21,7 +21,7 @@ import java.util.logging.Level; import java.util.logging.Logger; -import io.microprofile.config.spi.ConfigSource; +import org.eclipse.microprofile.config.spi.ConfigSource; /** @@ -31,6 +31,9 @@ * @author Gerhard Petracek */ public abstract class BaseConfigSource implements ConfigSource { + + public final static String CONFIG_ORDINAL = "config_ordinal"; + protected Logger log = Logger.getLogger(getClass().getName()); private int ordinal = 1000; // default @@ -50,7 +53,7 @@ public int getOrdinal() { protected void initOrdinal(int defaultOrdinal) { ordinal = defaultOrdinal; - String configuredOrdinalString = getPropertyValue(ConfigSource.CONFIG_ORDINAL); + String configuredOrdinalString = getValue(CONFIG_ORDINAL); try { if (configuredOrdinalString != null) { diff --git a/impl/src/main/java/org/apache/geronimo/config/configsource/PropertyFileConfigSource.java b/impl/src/main/java/org/apache/geronimo/config/configsource/PropertyFileConfigSource.java index d98826d..7d86394 100644 --- a/impl/src/main/java/org/apache/geronimo/config/configsource/PropertyFileConfigSource.java +++ b/impl/src/main/java/org/apache/geronimo/config/configsource/PropertyFileConfigSource.java @@ -42,12 +42,12 @@ public PropertyFileConfigSource(URL propertyFileUrl) { * @return value for the given key or null if there is no configured value */ @Override - public String getPropertyValue(String key) { - return (String) properties.get(key); + public String getValue(String key) { + return properties.get(key); } @Override - public String getConfigName() { + public String getName() { return fileName; } diff --git a/impl/src/main/java/org/apache/geronimo/config/configsource/PropertyFileConfigSourceProvider.java b/impl/src/main/java/org/apache/geronimo/config/configsource/PropertyFileConfigSourceProvider.java index 6404f92..f4be5fa 100644 --- a/impl/src/main/java/org/apache/geronimo/config/configsource/PropertyFileConfigSourceProvider.java +++ b/impl/src/main/java/org/apache/geronimo/config/configsource/PropertyFileConfigSourceProvider.java @@ -26,8 +26,8 @@ import java.util.logging.Level; import java.util.logging.Logger; -import io.microprofile.config.spi.ConfigSource; -import io.microprofile.config.spi.ConfigSourceProvider; +import org.eclipse.microprofile.config.spi.ConfigSource; +import org.eclipse.microprofile.config.spi.ConfigSourceProvider; /** diff --git a/impl/src/main/java/org/apache/geronimo/config/configsource/SystemEnvConfigSource.java b/impl/src/main/java/org/apache/geronimo/config/configsource/SystemEnvConfigSource.java index bf5e171..1c31cc6 100644 --- a/impl/src/main/java/org/apache/geronimo/config/configsource/SystemEnvConfigSource.java +++ b/impl/src/main/java/org/apache/geronimo/config/configsource/SystemEnvConfigSource.java @@ -21,7 +21,7 @@ import java.util.Map; -import io.microprofile.config.spi.ConfigSource; +import org.eclipse.microprofile.config.spi.ConfigSource; /** * {@link ConfigSource} which uses {@link System#getenv()} @@ -40,7 +40,7 @@ public SystemEnvConfigSource() { } @Override - public String getConfigName() { + public String getName() { return "system_env"; } @@ -50,7 +50,7 @@ public Map getProperties() { } @Override - public String getPropertyValue(String key) { + public String getValue(String key) { String val = configValues.get(key); if (val == null || val.isEmpty()) { val = configValues.get(key.replace('.', '_')); diff --git a/impl/src/main/java/org/apache/geronimo/config/configsource/SystemPropertyConfigSource.java b/impl/src/main/java/org/apache/geronimo/config/configsource/SystemPropertyConfigSource.java index 73ce7f1..f5f8ea1 100644 --- a/impl/src/main/java/org/apache/geronimo/config/configsource/SystemPropertyConfigSource.java +++ b/impl/src/main/java/org/apache/geronimo/config/configsource/SystemPropertyConfigSource.java @@ -20,7 +20,7 @@ import java.util.Map; -import io.microprofile.config.spi.ConfigSource; +import org.eclipse.microprofile.config.spi.ConfigSource; /** * {@link ConfigSource} which uses {@link System#getProperties()} @@ -38,12 +38,12 @@ public Map getProperties() { } @Override - public String getPropertyValue(String key) { + public String getValue(String key) { return System.getProperty(key); } @Override - public String getConfigName() { + public String getName() { return "system-properties"; } } diff --git a/impl/src/main/java/org/apache/geronimo/config/converters/BooleanConverter.java b/impl/src/main/java/org/apache/geronimo/config/converters/BooleanConverter.java index 72e03b4..e2b5d3c 100644 --- a/impl/src/main/java/org/apache/geronimo/config/converters/BooleanConverter.java +++ b/impl/src/main/java/org/apache/geronimo/config/converters/BooleanConverter.java @@ -16,7 +16,7 @@ */ package org.apache.geronimo.config.converters; -import io.microprofile.config.spi.Converter; +import org.eclipse.microprofile.config.spi.Converter; import javax.annotation.Priority; diff --git a/impl/src/main/java/org/apache/geronimo/config/converters/DoubleConverter.java b/impl/src/main/java/org/apache/geronimo/config/converters/DoubleConverter.java index c32860f..c1eb6fb 100644 --- a/impl/src/main/java/org/apache/geronimo/config/converters/DoubleConverter.java +++ b/impl/src/main/java/org/apache/geronimo/config/converters/DoubleConverter.java @@ -16,7 +16,7 @@ */ package org.apache.geronimo.config.converters; -import io.microprofile.config.spi.Converter; +import org.eclipse.microprofile.config.spi.Converter; import javax.annotation.Priority; diff --git a/impl/src/main/java/org/apache/geronimo/config/converters/FloatConverter.java b/impl/src/main/java/org/apache/geronimo/config/converters/FloatConverter.java index fa7372a..1a4eaac 100644 --- a/impl/src/main/java/org/apache/geronimo/config/converters/FloatConverter.java +++ b/impl/src/main/java/org/apache/geronimo/config/converters/FloatConverter.java @@ -18,7 +18,7 @@ import javax.annotation.Priority; -import io.microprofile.config.spi.Converter; +import org.eclipse.microprofile.config.spi.Converter; /** * @author Mark Struberg diff --git a/impl/src/main/java/org/apache/geronimo/config/converters/IntegerConverter.java b/impl/src/main/java/org/apache/geronimo/config/converters/IntegerConverter.java index cb76c63..be32e8a 100644 --- a/impl/src/main/java/org/apache/geronimo/config/converters/IntegerConverter.java +++ b/impl/src/main/java/org/apache/geronimo/config/converters/IntegerConverter.java @@ -18,7 +18,7 @@ import javax.annotation.Priority; -import io.microprofile.config.spi.Converter; +import org.eclipse.microprofile.config.spi.Converter; /** * @author Mark Struberg diff --git a/impl/src/main/java/org/apache/geronimo/config/converters/LongConverter.java b/impl/src/main/java/org/apache/geronimo/config/converters/LongConverter.java index 4df6eaa..dc63f5a 100644 --- a/impl/src/main/java/org/apache/geronimo/config/converters/LongConverter.java +++ b/impl/src/main/java/org/apache/geronimo/config/converters/LongConverter.java @@ -16,7 +16,7 @@ */ package org.apache.geronimo.config.converters; -import io.microprofile.config.spi.Converter; +import org.eclipse.microprofile.config.spi.Converter; import javax.annotation.Priority; diff --git a/impl/src/main/resources/META-INF/services/io.microprofile.config.ConfigProvider$SPI b/impl/src/main/resources/META-INF/services/org.eclipse.microprofile.config.spi.ConfigProviderResolver similarity index 100% rename from impl/src/main/resources/META-INF/services/io.microprofile.config.ConfigProvider$SPI rename to impl/src/main/resources/META-INF/services/org.eclipse.microprofile.config.spi.ConfigProviderResolver diff --git a/impl/tck-suite.xml b/impl/tck-suite.xml index ab445be..eff3f62 100644 --- a/impl/tck-suite.xml +++ b/impl/tck-suite.xml @@ -22,7 +22,7 @@ - + diff --git a/pom.xml b/pom.xml index cf08594..487e84b 100644 --- a/pom.xml +++ b/pom.xml @@ -45,15 +45,12 @@ - 1.7 - 1.7 + 1.8 + 1.8 - api - tck impl - spec diff --git a/spec/pom.xml b/spec/pom.xml deleted file mode 100644 index 6389337..0000000 --- a/spec/pom.xml +++ /dev/null @@ -1,98 +0,0 @@ - - - - 4.0.0 - - - - org.apache.geronimo.config - config-parent - 0.1-SNAPSHOT - - - org.apache.geronimo.config - config-spec - pom - - - - Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt - repo - A business-friendly OSS license - - - - - 1.5.3 - 1.5.0-alpha.10.1 - Apache License v 2.0 - MMMM dd, yyyy - ${maven.build.timestamp} - - - - clean package - - - org.asciidoctor - asciidoctor-maven-plugin - ${asciidoctor-maven.version} - - - org.asciidoctor - asciidoctorj-pdf - ${asciidoctorj-pdf.version} - - - - - generate-pdf-doc - generate-resources - - process-asciidoc - - - pdf - - - - output-html - generate-resources - - process-asciidoc - - - html5 - - - - - microprofile-config-spec.asciidoc - coderay - - Apache License v2.0 - - - - - - - diff --git a/spec/src/main/asciidoc/architecture.asciidoc b/spec/src/main/asciidoc/architecture.asciidoc deleted file mode 100644 index b715436..0000000 --- a/spec/src/main/asciidoc/architecture.asciidoc +++ /dev/null @@ -1,51 +0,0 @@ -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// See the NOTICE file distributed with this work -// for additional information regarding copyright ownership. -// The author 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. -// - -[[architecture]] -== Architecture - -This specification defines an easy to use and flexible system for application configuration. -It also defines a way to extend the configuration mechanism itself via a SPI (Service Provider Interface) in a portable way. - -=== Rational - -Released binaries often contain functionality which need to behave slightly differently depending on the deployment. -This might be different REST endpoints to talk to (e.g. depending on the customer for whom a WAR is deployed). -Or it might even be different features which need to be switched on and off depending on the installation. -All this must be possible without the need to re-package the whole application binary. - -Microprofile-Config provides a way to achieve this goal by aggregating configuration from many different <> and presents a single merged view to the user. -This allows the application to bundle default configuration within the application. -It also allows to override the defaults from outside, e.g. via an environment variable a Java system property or via Docker. -Microprofile-Config also allows to implement and register own configuration sources in a portable way, e.g. for reading configuration values from a shared database in an application cluster. - - -The core Microprofile-Config mechanism is purely String/String based. -Type-safety is only provided on top of that by using the proper <> before handing the value out to the caller. - -The configuration key might use dot-separated namespaces similar to Java package namespacing: - -[source, text] ----- -com.acme.myproject.someserver.url = http://some.server/some/endpoint -com.acme.myproject.someserver.port = 9085 -com.acme.myproject.someserver.active = true -com.acme.other.stuff.name = Karl -com.acme.myproject.notify.onerror=karl@mycompany,sue@mcompany ----- - -Config keys are usually case sensitive. diff --git a/spec/src/main/asciidoc/configexamples.asciidoc b/spec/src/main/asciidoc/configexamples.asciidoc deleted file mode 100644 index 4799e11..0000000 --- a/spec/src/main/asciidoc/configexamples.asciidoc +++ /dev/null @@ -1,92 +0,0 @@ -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// See the NOTICE file distributed with this work -// for additional information regarding copyright ownership. -// The author 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. -// - -[[configexamples]] -== Configuration Usage Examples - -An application can access it's configured values via a `Config` instance. -A user can use the `ConfigProvider` to access the `Config` of an application or simply use `@Inject Config` within CDI managed components. - -=== Simple Example - -[source, java] ----- -ppublic class ConfigUsageSample { - - public void useTheConfig() { - // get access to the Config instance - Config config = ConfigProvider.getConfig(); - - String serverUrl = config.getValue("com.acme.myproject.someserver.url"); - Integer serverPort = config.getValue("com.acme.myproject.someserver.port", - Integer.class); - - callToServer(serverUrl, serverPort); - } -} ----- - -If you need to access a different server then you can e.g. change the configuration via a `-D` system property: - -[source, text] ----- -$> java -jar some.jar -Dcom.acme.myproject.someserver.url=http://other.server/other/endpoint ----- - -Note that the way to inject this configuration into the application can be extended by providing custom `ConfigSource` s. - - - -=== Some advanced features - -It is also possible to dynamically pick up values which might change at runtime. -For example if the configured values get picked up from a custom <> which picks up it's values from a Database. - -[source, java] ----- -@ApplicationScoped -public class DynamicConfigUsageSample { - - private @Inject Config config; - - private ConfigValue serverUrlCfg; - private ConfigValue serverPortCfg - - @PostConstruct - private void init() { - serverUrlCfg= config.access("com.acme.myproject.someserver.url") - .cacheFor(5, TimeUnit.MINUTES) - .logChanges(true) - .evaluateVariables(true); - - serverPortCfg = config.access("com.acme.myproject.someserver.port") - .as(Integer.class) - .cacheFor(5, TimeUnit.MINUTES) - .logChanges(true) - .evaluateVariables(true) - .withDefault(8080); - } - - public void useTheConfig() { - callToServer(serverUrlCfg.getValue(), serverPortCfg.getValue()); - } -} ----- - -The `cacheFor(5, TimeUnit.MINUTES)` will have the `ConfigValue` behave like a local cache and thus reduce load on the configuration system. -5 minutes after `getValue()` got called the last time any fresh value will get picked up. -If `logChanges(true)` is set then any value change will get logged. \ No newline at end of file diff --git a/spec/src/main/asciidoc/configprovider.asciidoc b/spec/src/main/asciidoc/configprovider.asciidoc deleted file mode 100644 index ce39eb4..0000000 --- a/spec/src/main/asciidoc/configprovider.asciidoc +++ /dev/null @@ -1,57 +0,0 @@ -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// See the NOTICE file distributed with this work -// for additional information regarding copyright ownership. -// The author 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. -// - -[[configprovider]] -== Accessing or Creating a certain Configuration - - -For manually accessing the `ConfigProvider` is the central class to access a configuration. -It allows access to different configurations (represented by a `Config` instance) based on the application in which it is used. -We distinguish 5 different ways to create or `Config` instance: - -* In CDI manged components a user can use `@Inject` to access the current application configuration. - If no configuration is registered the automatic discovery of <> will be performed. - -* A factory method `ConfigProvider#getConfig()` to create a `Config` object based on automatically picked up `ConfigSources` - of the Application identified by the current Thread Context ClassLoader classpath. - Subsequent calls to this method for a certain Application will return the same `Config` instance. - -* A factory method `ConfigProvider#getConfig(ClassLoader forClassLoader)` to create a `Config` object based on automatically picked up `ConfigSources` - of the Application identified by the given ClassLoader. - This can be used if the Thread Context ClassLoader does not represent the correct layer. - E.g. if you need the Config for a class in a shared EAR lib folder. - Subsequent calls to this method for a certain Application will return the same `Config` instance. - -* A factory method `ConfigProvider#newConfig()` to create an empty `Config` object which can be filled manually via a builder. - This configuration instance will not be shared by the `ConfigProvider`. - This method is intended be used if a IoT container or any other external Factory can be used to give access to a manually created shared `Config`. - -* A factory method `ConfigProvider#registerConfig()` to create an empty `Config` object which can be filled manually via a builder. - This configuration instance *will* be shared by the `ConfigProvider`. - Any subsequent call to `ConfigProvider#getConfig()` will return the registered `Config` instance. - - -All methods in the `ConfigProvider` and `Config` implementations are thread safe and reentrant. - -If a `Config` is bound to an Application it is ensured that it gets properly removed if the Application gets destroyed. -The Config system deos not create any memory leaks in that case. - -A `Config` can be release manually by calling `ConfigProvider#release(Config)`. -ConfigSources which implement the `java.io.Closeable` interface will be properly destroyed. -Any subsequent call to `ConfigProvider#getConfig()` or `ConfigProvider#getConfig(ClassLoader forClassLoader)` will result in a new `Config` instance. - -<<< \ No newline at end of file diff --git a/spec/src/main/asciidoc/configsources.asciidoc b/spec/src/main/asciidoc/configsources.asciidoc deleted file mode 100644 index 22e5d85..0000000 --- a/spec/src/main/asciidoc/configsources.asciidoc +++ /dev/null @@ -1,137 +0,0 @@ -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// See the NOTICE file distributed with this work -// for additional information regarding copyright ownership. -// The author 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. -// - -[[configsource]] -== ConfigSource - -A `ConfigSource` is exactly what its name says: a source for configured values. -The `Config` uses all configured implementations of `ConfigSource` to look up the property in question. - -=== ConfigSource Ordering - -Each `ConfigSource` has a specified `ordinal`, which is used to determine the importance of the values taken from the associated `ConfigSource`. -A higher `ordinal` means that the values taken from this `ConfigSource` will override values from lower-priority `ConfigSource` s. -This allows a configuration to be customized from outside a binary, assuming that external `ConfigSource` s have higher `ordinal` values than the ones whose values originate within the release binaries. - -It can also be used to implement a drop-in configuration approach. -Simply create a jar containing a `ConfigSource` with a higher ordinal and override configuration values in it. -If the jar is present on the classpath then it will override configuration values from `ConfigSource` s with lower `ordinal` values. - -The ordinal for property file based `ConfigSource` s can be configured using the key `config_ordinal` inside the property file. - -[source, text] ----- -config_ordinal = 120 -com.acme.myproject.someserver.url = http://more_important.server/some/endpoint ----- - -[[default_configsources]] -=== Default ConfigSources - -A Microprofile-Config implementation must provide `ConfigSource` s for the following data out of the box: - -* System properties (ordinal=400) -* Environment properties (ordinal=300). - The built in `ConfigSource` for the environment provides an all upper-case fallback lookup where dots are replaced with underlines. - An environment setting `ACME_MYKEY=bla` machtches a lookup for `config.getValue("acme.mykey")`. -* A `ConfigSource` for each property file `META-INF/java-config.properties` found on the classpath. (default ordinal = 100) - -=== Custom ConfigSources - -`ConfigSource` s are discovered using the `java.util.ServiceLoader` mechanism. - -To add a custom `ConfigSource`, implement the interface `io.microprofile.config.spi.ConfigSource`. - -[source, java] ----- -public class CustomDbConfigSource implements ConfigSource { - - @Override - public int getOrdinal() { - return 112; - } - - @Override - public Map getProperties() { - return readPropertiesFromDb(); - } - - @Override - public String getPropertyValue(String key) { - return readPropertyFromDb(key); - } - - @Override - public String getConfigName() { - return "customDbConfig"; - } - - // + methods to read from the DB -} - ----- - -Then register your implementation in a resource file `/META-INF/services/io.microprofile.config.spi.ConfigSource` by including the fully-qualified class name of the custom implementation in the file. - - -=== Custom ConfigSources via ConfigSourceProvider - -If you need dynamic `ConfigSource` s you can also register a `ConfigSourceProvider` in a similar manner. -This is useful if you are required to dynamically pick up multiple `ConfigSource` s of the same kind; -for example, to pick up all `myproject.properties` resources from all the JARs in your classpath. - -A custom `ConfigSourceProvider` must implement the interface `io.microprofile.config.spi.ConfigSourceProvider`. -Register your implementation in a resource file `/META-INF/services/io.microprofile.config.spi.ConfigSourceProvider` by including the fully-qualified class name of the custom implementation/s in the file. - -An example which registers all YAML files with the name `exampleconfig.yaml`: - -[source, java] ----- -public class ExampleYamlConfigSourceProvider - implements io.microprofile.config.spi.ConfigSourceProvider { - @Override - public List getConfigSources(ClassLoader forClassLoader) { - List configSources = new ArrayList<>(); - - Enumeration yamlFiles - = forClassLoader.getResources("sampleconfig.yaml"); - while (yamlFiles.hasMoreElements()) { - configSources.add(new SampleYamlConfigSource(yamlFiles.nextElement())); - } - return configSources; - } -} ----- - -Please note that a single `ConfigSource` should be either registered directly or via a `ConfigSourceProvider`, but never both ways. - - -=== ConfigSource and Mutable Data - -A `Config` instance provides no caching but iterates over all `ConfigSources` for each `getValue(String)` operation. -A `ConfigSource` is allowed to cache the underlying values itself. - -Users might use the `cacheFor(long, TimeUnit)` method of a `ConfigValue` to pick up values which might change at runtime without penetrating the configuration system. - - -=== Manually adding ConfigSources - -A user can manually register `ConfigSource` s by using the method `void addConfigSources(List configSourcesToAdd)`. -This will add the given list to the already registered `ConfigSources` of the current `Config` instance. - -The order in which the `ConfigSources` are evaluated when using `Config#getValue(String key)` is independent of the order in which they were added to the `Config`; this depends only on the `ordinal` values of the available `ConfigSources`. - diff --git a/spec/src/main/asciidoc/converters.asciidoc b/spec/src/main/asciidoc/converters.asciidoc deleted file mode 100644 index 0131c39..0000000 --- a/spec/src/main/asciidoc/converters.asciidoc +++ /dev/null @@ -1,48 +0,0 @@ -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// See the NOTICE file distributed with this work -// for additional information regarding copyright ownership. -// The author 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. -// - -[[converter]] -== Converter - -For providing typeseafe configuration we need to convert from the configured Strings into target types. -This happens by providing `Converter` s in the `Config`. - -=== Built-in Converters - -The following `Converter` s are provided by Microprofile-Config by default: - -* `Boolean` , values for `true` (case insensitive) "true", "1", "YES", "Y" "JA" "J", "OUI". - Any other value will be interpreted as `false` -* `Integer` -* `Long` -* `Float` , a dot '.' is used to separate the fractional digits -* `Double` , a dot '.' is used to separate the fractional digits -* `java.util.Date` in ISO-8601 format (https://www.ietf.org/rfc/rfc3339.txt), e.g. YYYY-MM-DD. Remaining fractions are set to 0. -* Java8 `LocalDate` and `LocalDateTime`in ISO-8601 format - - -=== Adding custom Converters - -A custom `Converter` must implement the generic interface `io.microprofile.config.spi.Converter`. -The TypedParameter of the interface is the target type the String is converted to -You have to register your implementation in a file `/META-INF/services/io.microprofile.config.spi.Converter` by writing the fully qualified class name of the custom implementation into it. - -A custom `Converter` can define a priority with the `@javax.annotation.Priority` annotation. -If a Priority annotation isn't applied, a default priority of 100 is assumed. -The `Config` will use the `Converter` with the highest `Priority` for each target type. - -A custom `Converter` for a target type of any of the built-in Converters will overwrite the default Converter. diff --git a/spec/src/main/asciidoc/license-alv2.asciidoc b/spec/src/main/asciidoc/license-alv2.asciidoc deleted file mode 100644 index 276af0a..0000000 --- a/spec/src/main/asciidoc/license-alv2.asciidoc +++ /dev/null @@ -1,44 +0,0 @@ -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// See the NOTICE file distributed with this work -// for additional information regarding copyright ownership. -// The author 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. -// - -[subs="normal"] -.... - -Specification: {doctitle} - -Version: {revnumber} - -Status: {revremark} - -Specification Lead: Mark Struberg, Emily Jiang - -Release: {revdate} - -Copyright 2016-2017 Original Authors, -Licensed 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. - -.... diff --git a/spec/src/main/asciidoc/microprofile-config-spec.asciidoc b/spec/src/main/asciidoc/microprofile-config-spec.asciidoc deleted file mode 100644 index eca5e96..0000000 --- a/spec/src/main/asciidoc/microprofile-config-spec.asciidoc +++ /dev/null @@ -1,46 +0,0 @@ -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// See the NOTICE file distributed with this work -// for additional information regarding copyright ownership. -// The author 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. -// - -= Configuration for Microprofile -:author: Mark Struberg -:email: struberg@apache.org -:revnumber: 0.2 -:revdate: 2017-01-15 -:revremark: Proposal -:version-label!: -:sectanchors: -:doctype: book -:license: Apache License v2.0 -:source-highlighter: coderay -:toc: left -:toclevels: 4 -:sectnumlevels: 4 -ifdef::backend-pdf[] -:pagenums: -endif::[] - -include::license-alv2.asciidoc[] - -include::architecture.asciidoc[] - -include::configexamples.asciidoc[] - -include::configprovider.asciidoc[] - -include::configsources.asciidoc[] - -include::converters.asciidoc[] diff --git a/tck/pom.xml b/tck/pom.xml deleted file mode 100644 index cff61bd..0000000 --- a/tck/pom.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - 4.0.0 - - - org.apache.geronimo.config - config-parent - 0.1-SNAPSHOT - - - org.apache.geronimo.config - config-tck - - - - Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt - repo - A business-friendly OSS license - - - - - - org.apache.geronimo.config - config-api - 0.1-SNAPSHOT - - - - org.testng - testng - 6.9.9 - compile - - - diff --git a/tck/src/main/java/io/microprofile/config/tck/ConfigProviderTest.java b/tck/src/main/java/io/microprofile/config/tck/ConfigProviderTest.java deleted file mode 100644 index 6b9a4b0..0000000 --- a/tck/src/main/java/io/microprofile/config/tck/ConfigProviderTest.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * 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 io.microprofile.config.tck; - -import java.net.URL; -import java.net.URLClassLoader; -import java.util.Map; -import java.util.Properties; - -import io.microprofile.config.Config; -import io.microprofile.config.ConfigProvider; - -import io.microprofile.config.tck.configsources.SampleYamlConfigSource; -import org.testng.Assert; -import org.testng.annotations.Test; - -/** - * @author Mark Struberg - */ -public class ConfigProviderTest { - - @Test - public void testConfigProviderWithDefaultTCCL() { - ClassLoader oldTccl = Thread.currentThread().getContextClassLoader(); - try { - ClassLoader tempCl = new URLClassLoader(new URL[0], this.getClass().getClassLoader()); - Thread.currentThread().setContextClassLoader(tempCl); - Config config = ConfigProvider.getConfig(); - Assert.assertNotNull(config); - - Config config2 = ConfigProvider.getConfig(tempCl); - Assert.assertNotNull(config2); - Assert.assertEquals(config, config2); - } - finally { - Thread.currentThread().setContextClassLoader(oldTccl); - } - } - - @Test - public void testEnvironmentConfigSource() { - Map env = System.getenv(); - Config config = ConfigProvider.getConfig(); - for (Map.Entry envEntry : env.entrySet()) { - Assert.assertEquals(envEntry.getValue(), config.getValue(envEntry.getKey())); - } - } - - @Test - public void testPropertyConfigSource() { - Properties properties = System.getProperties(); - Config config = ConfigProvider.getConfig(); - - for (Map.Entry propEntry : properties.entrySet()) { - Assert.assertEquals(propEntry.getValue(), config.getValue((String) propEntry.getKey())); - } - } - - @Test - public void testDynamicValueInPropertyConfigSource() { - Config config = ConfigProvider.getConfig(); - String configKey = "tck.config.test.systemproperty.dynamic.value"; - String configValue = "myDynamicValue;"; - - System.setProperty(configKey, configValue); - Assert.assertEquals(config.getValue(configKey), configValue); - } - - @Test - public void testJavaConfigPropertyFilesConfigSource() { - Config config = ConfigProvider.getConfig(); - Assert.assertEquals(config.getValue("tck.config.test.javaconfig.properties.key1"), "VALue1"); - } - - @Test - public void testNonExistingConfigKey() { - Config config = ConfigProvider.getConfig(); - Assert.assertNull(config.getValue("tck.config.test.keydoesnotexist")); - } - - @Test - public void testRegisterManualConfig() { - // make sure we get a clean config - ConfigProvider.releaseConfig(ConfigProvider.getConfig()); - - ConfigProvider.registerConfig() - .ignoreDefaultSources() - .withSources(new SampleYamlConfigSource(null)) - .build(); - - Config config = ConfigProvider.getConfig(); - Assert.assertNotNull(config); - Assert.assertNotNull(config.getConfigSources()); - Assert.assertEquals(1, config.getConfigSources().length); - Assert.assertEquals(SampleYamlConfigSource.class, config.getConfigSources()[0].getClass()); - - Assert.assertEquals("yamlvalue1", config.getValue("tck.config.test.sampleyaml.key1")); - - Assert.assertNull(config.getValue("tck.config.test.javaconfig.properties.key1")); - - { - // try it again, Sam - // this time we should fail as we already have a Config registered for this application - try { - ConfigProvider.registerConfig() - .ignoreDefaultSources() - .withSources(new SampleYamlConfigSource(null)) - .build(); - - Assert.fail("We fail because subsequently registering another Config for the application is not allowed"); - } - catch (IllegalStateException ise) { - // all fine - } - } - - // clean up the dirt afterwards - ConfigProvider.releaseConfig(ConfigProvider.getConfig()); - } - - @Test - public void testConfigProviderRelease() { - Config config1 = ConfigProvider.getConfig(); - Config config2 = ConfigProvider.getConfig(); - - Assert.assertEquals(config2, config1); - - ConfigProvider.releaseConfig(config2); - - Config config3 = ConfigProvider.getConfig(); - - Assert.assertNotEquals(config1, config3); - } -} diff --git a/tck/src/main/java/io/microprofile/config/tck/ConfigSourceProviderTest.java b/tck/src/main/java/io/microprofile/config/tck/ConfigSourceProviderTest.java deleted file mode 100644 index 28a65a9..0000000 --- a/tck/src/main/java/io/microprofile/config/tck/ConfigSourceProviderTest.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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 io.microprofile.config.tck; - -import io.microprofile.config.Config; -import io.microprofile.config.ConfigProvider; -import org.testng.Assert; -import org.testng.annotations.Test; - -/** - * @author Mark Struberg - */ -public class ConfigSourceProviderTest { - - @Test - public void testConfigSourceProvider() { - Config config = ConfigProvider.getConfig(); - - Assert.assertEquals(config.getValue("tck.config.test.sampleyaml.key1"), "yamlvalue1"); - } -} diff --git a/tck/src/main/java/io/microprofile/config/tck/ConfigValueTest.java b/tck/src/main/java/io/microprofile/config/tck/ConfigValueTest.java deleted file mode 100644 index 575f00a..0000000 --- a/tck/src/main/java/io/microprofile/config/tck/ConfigValueTest.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * 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 io.microprofile.config.tck; - -import io.microprofile.config.Config; -import io.microprofile.config.ConfigProvider; -import io.microprofile.config.ConfigValue; -import org.testng.Assert; -import org.testng.annotations.Test; - -import java.util.concurrent.TimeUnit; - -/** - * @author Mark Struberg - */ -public class ConfigValueTest { - - private Config config = ConfigProvider.getConfig(); - - @Test - public void testGetValue() { - Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.key1").getValue(), "value1"); - } - - @Test - public void testGetValueWithDefault() { - ConfigValue cfga = config.access("tck.config.test.javaconfig.configvalue.withdefault.notexisting") - .as(Integer.class) - .withDefault(Integer.valueOf(1234)); - - Assert.assertEquals(cfga.getValue(), Integer.valueOf(1234)); - } - - @Test - public void testGetValueWithStringDefault() { - ConfigValue cfga = config.access("tck.config.test.javaconfig.configvalue.withdefault.notexisting") - .as(Integer.class) - .withStringDefault("1234"); - - Assert.assertEquals(cfga.getValue(), Integer.valueOf(1234)); - } - - @Test - public void testIntegerConverter() { - Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.integer").as(Integer.class).getValue(), Integer.valueOf(1234)); - } - - @Test - public void testLongConverter() { - Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.long").as(Long.class).getValue(), Long.valueOf(1234567890123456L)); - } - - @Test - public void testFloatConverter() { - Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.float").as(Float.class).getValue(), Float.valueOf(12.34f)); - } - - @Test - public void testDoubleonverter() { - Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.double").as(Double.class).getValue(), Double.valueOf(12.34567890123456)); - } - - @Test - public void testBooleanConverter() { - Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.true").as(Boolean.class).getValue(), Boolean.TRUE); - Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.true_uppercase").as(Boolean.class).getValue(), Boolean.TRUE); - Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.true_mixedcase").as(Boolean.class).getValue(), Boolean.TRUE); - Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.false").as(Boolean.class).getValue(), Boolean.FALSE); - - Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.one").as(Boolean.class).getValue(), Boolean.TRUE); - Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.zero").as(Boolean.class).getValue(), Boolean.FALSE); - Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.seventeen").as(Boolean.class).getValue(), Boolean.FALSE); - - Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.yes").as(Boolean.class).getValue(), Boolean.TRUE); - Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.yes_uppercase").as(Boolean.class).getValue(), Boolean.TRUE); - Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.yes_mixedcase").as(Boolean.class).getValue(), Boolean.TRUE); - - Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.y").as(Boolean.class).getValue(), Boolean.TRUE); - Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.y_uppercase").as(Boolean.class).getValue(), Boolean.TRUE); - - Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.ja").as(Boolean.class).getValue(), Boolean.TRUE); - Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.ja_uppercase").as(Boolean.class).getValue(), Boolean.TRUE); - Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.ja_mixedcase").as(Boolean.class).getValue(), Boolean.TRUE); - Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.no_mixedcase").as(Boolean.class).getValue(), Boolean.FALSE); - - Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.j").as(Boolean.class).getValue(), Boolean.TRUE); - Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.j_uppercase").as(Boolean.class).getValue(), Boolean.TRUE); - Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.n_uppercase").as(Boolean.class).getValue(), Boolean.FALSE); - - Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.oui").as(Boolean.class).getValue(), Boolean.TRUE); - Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.oui_uppercase").as(Boolean.class).getValue(), Boolean.TRUE); - Assert.assertEquals(config.access("tck.config.test.javaconfig.configvalue.boolean.oui_mixedcase").as(Boolean.class).getValue(), Boolean.TRUE); - } - - @Test - public void testCacheFor() throws Exception { - String key = "tck.config.cachefor.key"; - System.setProperty(key, "firstvalue"); - ConfigValue val = config.access(key).cacheFor(30, TimeUnit.MILLISECONDS); - Assert.assertEquals(val.getValue(), "firstvalue"); - - // immediately change the value - System.setProperty(key, "secondvalue"); - - // we should still see the first value, because it is cached! - Assert.assertEquals(val.getValue(), "firstvalue"); - - // but now let's wait a bit - Thread.sleep(40); - Assert.assertEquals(val.getValue(), "secondvalue"); - } - - @Test - public void testWithVariable() throws Exception { - ConfigValue val = config.access("tck.config.test.javaconfig.configvalue.withvariable.key").evaluateVariables(true); - Assert.assertEquals(val.getValue(), "This key needs the perfect value!"); - } -} diff --git a/tck/src/main/java/io/microprofile/config/tck/ConverterTest.java b/tck/src/main/java/io/microprofile/config/tck/ConverterTest.java deleted file mode 100644 index bbb0419..0000000 --- a/tck/src/main/java/io/microprofile/config/tck/ConverterTest.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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 io.microprofile.config.tck; - -import io.microprofile.config.Config; -import io.microprofile.config.ConfigProvider; -import org.testng.Assert; -import org.testng.annotations.Test; - -/** - * @author Mark Struberg - */ -public class ConverterTest { - - @Test - public void testIntegerConverter() { - Config config = ConfigProvider.getConfig(); - Integer value = config.getValue("tck.config.test.javaconfig.converter.integervalue", Integer.class); - Assert.assertEquals(value, Integer.valueOf(1234)); - - } - - @Test - public void testFloatConverter() { - Config config = ConfigProvider.getConfig(); - Float value = config.getValue("tck.config.test.javaconfig.converter.floatvalue", Float.class); - Assert.assertEquals(value, Float.valueOf(12.34f)); - - } - - -} diff --git a/tck/src/main/java/io/microprofile/config/tck/CustomConfigSourceTest.java b/tck/src/main/java/io/microprofile/config/tck/CustomConfigSourceTest.java deleted file mode 100644 index 5a8d80d..0000000 --- a/tck/src/main/java/io/microprofile/config/tck/CustomConfigSourceTest.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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 io.microprofile.config.tck; - -import io.microprofile.config.Config; -import io.microprofile.config.ConfigProvider; -import org.testng.Assert; -import org.testng.annotations.Test; - -/** - * @author Mark Struberg - */ -public class CustomConfigSourceTest { - - @Test - public void testConfigSourceProvider() { - Config config = ConfigProvider.getConfig(); - - Assert.assertEquals(config.getValue("tck.config.test.customDbConfig.key1"), "valueFromDb1"); - } -} diff --git a/tck/src/main/java/io/microprofile/config/tck/configsources/CustomConfigSourceProvider.java b/tck/src/main/java/io/microprofile/config/tck/configsources/CustomConfigSourceProvider.java deleted file mode 100644 index 2f2d0c4..0000000 --- a/tck/src/main/java/io/microprofile/config/tck/configsources/CustomConfigSourceProvider.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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 io.microprofile.config.tck.configsources; - -import java.io.IOException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.List; - -import io.microprofile.config.spi.ConfigSource; -import io.microprofile.config.spi.ConfigSourceProvider; - -/** - * @author Mark Struberg - */ -public class CustomConfigSourceProvider implements ConfigSourceProvider { - @Override - public List getConfigSources(ClassLoader forClassLoader) { - List detectedConfigSources = new ArrayList<>(); - - Enumeration yamlFiles = null; - try { - yamlFiles = forClassLoader.getResources("sampleconfig.yaml"); - } catch (IOException e) { - throw new RuntimeException(e); - } - while (yamlFiles.hasMoreElements()) { - detectedConfigSources.add(new SampleYamlConfigSource(yamlFiles.nextElement())); - } - return detectedConfigSources; - } -} diff --git a/tck/src/main/java/io/microprofile/config/tck/configsources/CustomDbConfigSource.java b/tck/src/main/java/io/microprofile/config/tck/configsources/CustomDbConfigSource.java deleted file mode 100644 index 83e27a1..0000000 --- a/tck/src/main/java/io/microprofile/config/tck/configsources/CustomDbConfigSource.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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 io.microprofile.config.tck.configsources; - -import java.util.HashMap; -import java.util.Map; - -import io.microprofile.config.spi.ConfigSource; - -/** - * @author Mark Struberg - */ -public class CustomDbConfigSource implements ConfigSource { - - private Map configValues = new HashMap<>(); - - public CustomDbConfigSource() { - configValues.put("tck.config.test.customDbConfig.key1", "valueFromDb1"); - configValues.put("tck.config.test.customDbConfig.key2", "valueFromDb2"); - } - - @Override - public int getOrdinal() { - return 112; - } - - @Override - public Map getProperties() { - return readPropertiesFromDb(); - } - - @Override - public String getPropertyValue(String key) { - return readPropertyFromDb(key); - } - - @Override - public String getConfigName() { - return "customDbConfig"; - } - - private Map readPropertiesFromDb() { - return configValues; - } - - private String readPropertyFromDb(String key) { - return configValues.get(key); - } -} diff --git a/tck/src/main/java/io/microprofile/config/tck/configsources/SampleYamlConfigSource.java b/tck/src/main/java/io/microprofile/config/tck/configsources/SampleYamlConfigSource.java deleted file mode 100644 index 1d64de5..0000000 --- a/tck/src/main/java/io/microprofile/config/tck/configsources/SampleYamlConfigSource.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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 io.microprofile.config.tck.configsources; - -import java.net.URL; -import java.util.HashMap; -import java.util.Map; - -import io.microprofile.config.spi.ConfigSource; - -/** - * @author Mark Struberg - */ -public class SampleYamlConfigSource implements ConfigSource { - private Map config = new HashMap<>(); - - public SampleYamlConfigSource(URL url) { - config.put("tck.config.test.sampleyaml.key1", "yamlvalue1"); - } - - @Override - public int getOrdinal() { - return config.get("ordinal") != null ? Integer.valueOf(config.get("ordinal")) : 110; - } - - @Override - public Map getProperties() { - return config; - } - - @Override - public String getPropertyValue(String key) { - return config.get(key); - } - - @Override - public String getConfigName() { - return null; - } - -} diff --git a/tck/src/main/java/io/microprofile/config/tck/converters/Duck.java b/tck/src/main/java/io/microprofile/config/tck/converters/Duck.java deleted file mode 100644 index 23a0542..0000000 --- a/tck/src/main/java/io/microprofile/config/tck/converters/Duck.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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 io.microprofile.config.tck.converters; - -/** - * @author Mark Struberg - */ -public class Duck { - private final String name; - - - public Duck(String name) { - this.name = name; - } - - public String getName() { - return name; - } -} diff --git a/tck/src/main/java/io/microprofile/config/tck/converters/DuckConverter.java b/tck/src/main/java/io/microprofile/config/tck/converters/DuckConverter.java deleted file mode 100644 index b653fc1..0000000 --- a/tck/src/main/java/io/microprofile/config/tck/converters/DuckConverter.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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 io.microprofile.config.tck.converters; - -import io.microprofile.config.spi.Converter; - -/** - * @author Mark Struberg - */ -public class DuckConverter implements Converter { - - @Override - public Duck convert(String value) { - return new Duck(value); - } -} diff --git a/tck/src/main/resources/META-INF/java-config.properties b/tck/src/main/resources/META-INF/java-config.properties deleted file mode 100644 index 8d478f9..0000000 --- a/tck/src/main/resources/META-INF/java-config.properties +++ /dev/null @@ -1,73 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy current the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - - -tck.config.test.javaconfig.properties.key1=VALue1 - - -tck.config.test.overwritten.in.custompropertyfile.key1=value from java-config.properties - - -tck.config.test.javaconfig.converter.integervalue = 1234 -tck.config.test.javaconfig.converter.floatvalue = 12.34 - - -tck.config.test.javaconfig.configvalue.key1=value1 - -# test BooleanConverter START -tck.config.test.javaconfig.configvalue.boolean.true=true -tck.config.test.javaconfig.configvalue.boolean.true_uppercase=TRUE -tck.config.test.javaconfig.configvalue.boolean.true_mixedcase=TruE -tck.config.test.javaconfig.configvalue.boolean.false=false - -tck.config.test.javaconfig.configvalue.boolean.one=1 -tck.config.test.javaconfig.configvalue.boolean.zero=0 -tck.config.test.javaconfig.configvalue.boolean.seventeen=17 - -tck.config.test.javaconfig.configvalue.boolean.yes=yes -tck.config.test.javaconfig.configvalue.boolean.yes_uppercase=YES -tck.config.test.javaconfig.configvalue.boolean.yes_mixedcase=Yes - -tck.config.test.javaconfig.configvalue.boolean.y=y -tck.config.test.javaconfig.configvalue.boolean.y_uppercase=Y - -tck.config.test.javaconfig.configvalue.boolean.ja=ja -tck.config.test.javaconfig.configvalue.boolean.ja_uppercase=ja -tck.config.test.javaconfig.configvalue.boolean.ja_mixedcase=Ja -tck.config.test.javaconfig.configvalue.boolean.no_mixedcase=No - -tck.config.test.javaconfig.configvalue.boolean.j=j -tck.config.test.javaconfig.configvalue.boolean.j_uppercase=J -tck.config.test.javaconfig.configvalue.boolean.n_uppercase=N - -tck.config.test.javaconfig.configvalue.boolean.oui=oui -tck.config.test.javaconfig.configvalue.boolean.oui_uppercase=OUI -tck.config.test.javaconfig.configvalue.boolean.oui_mixedcase=Oui -# test BooleanConverter END - -# various other converter -tck.config.test.javaconfig.configvalue.integer=1234 -tck.config.test.javaconfig.configvalue.long=1234567890123456 -tck.config.test.javaconfig.configvalue.float=12.34 -tck.config.test.javaconfig.configvalue.double=12.34567890123456 - - -# withVariable -tck.config.test.javaconfig.configvalue.variable = the perfect value -tck.config.test.javaconfig.configvalue.withvariable.key = This key needs ${tck.config.test.javaconfig.configvalue.variable}! \ No newline at end of file diff --git a/tck/src/main/resources/META-INF/services/io.microprofile.config.spi.ConfigSource b/tck/src/main/resources/META-INF/services/io.microprofile.config.spi.ConfigSource deleted file mode 100644 index 677a9fb..0000000 --- a/tck/src/main/resources/META-INF/services/io.microprofile.config.spi.ConfigSource +++ /dev/null @@ -1,20 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy current the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -io.microprofile.config.tck.configsources.CustomDbConfigSource \ No newline at end of file diff --git a/tck/src/main/resources/META-INF/services/io.microprofile.config.spi.ConfigSourceProvider b/tck/src/main/resources/META-INF/services/io.microprofile.config.spi.ConfigSourceProvider deleted file mode 100644 index bbcd7a0..0000000 --- a/tck/src/main/resources/META-INF/services/io.microprofile.config.spi.ConfigSourceProvider +++ /dev/null @@ -1,20 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy current the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -io.microprofile.config.tck.configsources.CustomConfigSourceProvider \ No newline at end of file diff --git a/tck/src/main/resources/sampleconfig.yaml b/tck/src/main/resources/sampleconfig.yaml deleted file mode 100644 index ee228a4..0000000 --- a/tck/src/main/resources/sampleconfig.yaml +++ /dev/null @@ -1,20 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy current the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# -# just needed as a trigger for the ConfigSource pickup. -# Content is hardcoded in SampleYamlConfigSource \ No newline at end of file From 9edcde41362d490a4800537f1d3c32626f0baf77 Mon Sep 17 00:00:00 2001 From: Mark Struberg Date: Fri, 10 Mar 2017 00:22:28 +0100 Subject: [PATCH 16/29] disable travis for now as the API isn't available on any repo yet and I removed the original version from here --- .travis.yml => .travis.yml.disabled | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .travis.yml => .travis.yml.disabled (100%) diff --git a/.travis.yml b/.travis.yml.disabled similarity index 100% rename from .travis.yml rename to .travis.yml.disabled From 4d956ba82f2ef4f2602db15d89cf9cdefc453b3b Mon Sep 17 00:00:00 2001 From: Mark Struberg Date: Fri, 10 Mar 2017 10:39:49 +0100 Subject: [PATCH 17/29] apply latest spec changes --- impl/pom.xml | 4 ++-- .../apache/geronimo/config/ConfigImpl.java | 23 +++++++++++-------- .../config/DefaultConfigProvider.java | 7 ++---- impl/tck-suite.xml | 8 ++----- pom.xml | 2 +- 5 files changed, 20 insertions(+), 24 deletions(-) diff --git a/impl/pom.xml b/impl/pom.xml index 618a423..0199f08 100644 --- a/impl/pom.xml +++ b/impl/pom.xml @@ -32,8 +32,8 @@ - org.eclipse.microprofile.config.api - microprofile-config-api + org.eclipse.microprofile.apis + microprofile-config_1.0_api 1.0-SNAPSHOT diff --git a/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java b/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java index 89bf067..9e62c31 100644 --- a/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java +++ b/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java @@ -19,7 +19,6 @@ import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; @@ -49,7 +48,7 @@ public class ConfigImpl implements Config { protected Logger logger = Logger.getLogger(ConfigImpl.class.getName()); - protected ConfigSource[] configSources = new ConfigSource[0]; + protected List configSources = new ArrayList<>(); protected Map converters = new HashMap<>(); @@ -67,7 +66,11 @@ private void registerDefaultConverter() { @Override public Optional getString(String key) { - return Optional.ofNullable(getValue(key)); + String val = getValue(key); + if (val == null || val.isEmpty()) { + return Optional.empty(); + } + return Optional.ofNullable(val); } public String getValue(String key) { @@ -117,9 +120,9 @@ public ConfigValue access(String key) { public Iterable getPropertyNames() { Set result = new HashSet<>(); - for (int i = configSources.length; i > 0; i--) { - ConfigSource configSource = configSources[i]; + for (ConfigSource configSource : configSources) { result.addAll(configSource.getProperties().keySet()); + } return result; } @@ -127,12 +130,12 @@ public Iterable getPropertyNames() { @Override - public ConfigSource[] getConfigSources() { - return configSources; + public Iterable getConfigSources() { + return Collections.unmodifiableList(configSources); } public synchronized void addConfigSources(List configSourcesToAdd) { - List allConfigSources = new ArrayList<>(Arrays.asList(configSources)); + List allConfigSources = new ArrayList<>(configSources); allConfigSources.addAll(configSourcesToAdd); // finally put all the configSources back into the map @@ -171,14 +174,14 @@ public Map getConverters() { } - protected ConfigSource[] sortDescending(List configSources) { + protected List sortDescending(List configSources) { Collections.sort(configSources, new Comparator() { @Override public int compare(ConfigSource configSource1, ConfigSource configSource2) { return (configSource1.getOrdinal() > configSource2.getOrdinal()) ? -1 : 1; } }); - return configSources.toArray(new ConfigSource[configSources.size()]); + return configSources; } diff --git a/impl/src/main/java/org/apache/geronimo/config/DefaultConfigProvider.java b/impl/src/main/java/org/apache/geronimo/config/DefaultConfigProvider.java index 0d280ed..09e3767 100644 --- a/impl/src/main/java/org/apache/geronimo/config/DefaultConfigProvider.java +++ b/impl/src/main/java/org/apache/geronimo/config/DefaultConfigProvider.java @@ -66,7 +66,8 @@ Config existingConfig(ClassLoader forClassLoader) { } - void registerConfig(Config config, ClassLoader forClassLoader) { + @Override + public void registerConfig(Config config, ClassLoader forClassLoader) { synchronized (DefaultConfigProvider.class) { configs.put(forClassLoader, new WeakReference<>(config)); } @@ -77,10 +78,6 @@ public ConfigBuilder getBuilder() { return new DefaultConfigBuilder(); } - @Override - public void setConfig(Config config, ClassLoader classLoader) { - registerConfig(config, classLoader); - } @Override public void releaseConfig(Config config) { diff --git a/impl/tck-suite.xml b/impl/tck-suite.xml index eff3f62..f0033e6 100644 --- a/impl/tck-suite.xml +++ b/impl/tck-suite.xml @@ -15,18 +15,14 @@ the specific language governing permissions and limitations under the License. --> - - - - - + + - diff --git a/pom.xml b/pom.xml index 487e84b..05e8c78 100644 --- a/pom.xml +++ b/pom.xml @@ -67,7 +67,7 @@ - .travis.yml + .travis.yml.* From a1a1dbdfa19427824eeb8e443aea3b51fd3c9fbb Mon Sep 17 00:00:00 2001 From: Mark Struberg Date: Fri, 10 Mar 2017 17:51:56 +0100 Subject: [PATCH 18/29] move to arquillian for CDI integration --- impl/pom.xml | 87 +++++++++++++++++++ .../config/ConfigInjectionProducer.java | 37 ++++++++ .../geronimo/config/DefaultConfigBuilder.java | 2 +- impl/src/main/resources/META-INF/beans.xml | 0 4 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 impl/src/main/java/org/apache/geronimo/config/ConfigInjectionProducer.java create mode 100644 impl/src/main/resources/META-INF/beans.xml diff --git a/impl/pom.xml b/impl/pom.xml index 0199f08..8c1790f 100644 --- a/impl/pom.xml +++ b/impl/pom.xml @@ -30,6 +30,23 @@ org.apache.geronimo.config config-impl + + 1.1.7.Final + + + + + + org.jboss.arquillian + arquillian-bom + ${arquillian.version} + pom + import + + + + + org.eclipse.microprofile.apis @@ -57,6 +74,15 @@ provided + + org.jboss.arquillian.testng + arquillian-testng-container + ${arquillian.version} + test + + + + @@ -73,4 +99,65 @@ + + + + OWB + + true + + + + 1.7.1 + + + + + org.apache.geronimo.specs + geronimo-atinject_1.0_spec + 1.0 + provided + + + org.apache.geronimo.specs + geronimo-jcdi_1.1_spec + 1.0 + provided + + + org.apache.geronimo.specs + geronimo-interceptor_1.2_spec + 1.0 + provided + + + org.apache.geronimo.specs + geronimo-el_2.2_spec + 1.0.2 + provided + + + + org.apache.openwebbeans + openwebbeans-spi + ${owb.version} + test + + + org.apache.openwebbeans + openwebbeans-impl + ${owb.version} + test + + + org.apache.openwebbeans.arquillian + owb-arquillian-standalone + ${owb.version} + test + + + + + + diff --git a/impl/src/main/java/org/apache/geronimo/config/ConfigInjectionProducer.java b/impl/src/main/java/org/apache/geronimo/config/ConfigInjectionProducer.java new file mode 100644 index 0000000..049366d --- /dev/null +++ b/impl/src/main/java/org/apache/geronimo/config/ConfigInjectionProducer.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.geronimo.config; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.inject.Produces; + +import org.eclipse.microprofile.config.Config; +import org.eclipse.microprofile.config.ConfigProvider; + +/** + * @author Mark Struberg + */ +@ApplicationScoped +public class ConfigInjectionProducer { + + @Produces + @ApplicationScoped + public Config createConfig() { + return ConfigProvider.getConfig(); + } + +} diff --git a/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java b/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java index 49fbad0..0362c73 100644 --- a/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java +++ b/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java @@ -102,7 +102,7 @@ protected Collection getBuiltInConfigSources(ClassLoader configSources.add(new SystemEnvConfigSource()); configSources.add(new SystemPropertyConfigSource()); - configSources.addAll(new PropertyFileConfigSourceProvider("META-INF/microprofile-config.properties", true, forClassLoader).getConfigSources(forClassLoader)); + configSources.addAll(new PropertyFileConfigSourceProvider("internal/META-INF/microprofile-config.properties", true, forClassLoader).getConfigSources(forClassLoader)); return configSources; } diff --git a/impl/src/main/resources/META-INF/beans.xml b/impl/src/main/resources/META-INF/beans.xml new file mode 100644 index 0000000..e69de29 From 231c7a05ab353e1f38b4546ad10277cd524a7e9a Mon Sep 17 00:00:00 2001 From: Mark Struberg Date: Fri, 10 Mar 2017 17:56:36 +0100 Subject: [PATCH 19/29] add missing license --- impl/src/main/resources/META-INF/beans.xml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/impl/src/main/resources/META-INF/beans.xml b/impl/src/main/resources/META-INF/beans.xml index e69de29..48bb5d2 100644 --- a/impl/src/main/resources/META-INF/beans.xml +++ b/impl/src/main/resources/META-INF/beans.xml @@ -0,0 +1,18 @@ + From ef969116302dfc7493eae5f25ae7c532446fabbb Mon Sep 17 00:00:00 2001 From: Mark Struberg Date: Mon, 13 Mar 2017 22:34:33 +0100 Subject: [PATCH 20/29] CDI integration adopted to new TCK This currently needs a bugfix in the OWB Arquillian container to work --- impl/pom.xml | 2 +- .../apache/geronimo/config/ConfigImpl.java | 2 + .../geronimo/config/ConfigValueImpl.java | 3 + .../geronimo/config/DefaultConfigBuilder.java | 5 +- .../config/DefaultConfigProvider.java | 4 ++ .../ManualApplicationConfigBuilder.java | 49 ---------------- .../{ => cdi}/ConfigInjectionProducer.java | 2 +- .../test/GeronimoConfigArchiveProcessor.java | 56 +++++++++++++++++++ .../config/test/GeronimoConfigExtension.java | 30 ++++++++++ ...boss.arquillian.core.spi.LoadableExtension | 21 +++++++ 10 files changed, 122 insertions(+), 52 deletions(-) delete mode 100644 impl/src/main/java/org/apache/geronimo/config/ManualApplicationConfigBuilder.java rename impl/src/main/java/org/apache/geronimo/config/{ => cdi}/ConfigInjectionProducer.java (96%) create mode 100644 impl/src/test/java/org/apache/geronimo/config/test/GeronimoConfigArchiveProcessor.java create mode 100644 impl/src/test/java/org/apache/geronimo/config/test/GeronimoConfigExtension.java create mode 100644 impl/src/test/resources/META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension diff --git a/impl/pom.xml b/impl/pom.xml index 8c1790f..c4b5177 100644 --- a/impl/pom.xml +++ b/impl/pom.xml @@ -108,7 +108,7 @@ - 1.7.1 + 1.7.3-SNAPSHOT diff --git a/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java b/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java index 9e62c31..4884ef2 100644 --- a/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java +++ b/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java @@ -41,10 +41,12 @@ import org.apache.geronimo.config.converters.LongConverter; import javax.annotation.Priority; +import javax.enterprise.inject.Typed; /** * @author Mark Struberg */ +@Typed public class ConfigImpl implements Config { protected Logger logger = Logger.getLogger(ConfigImpl.class.getName()); diff --git a/impl/src/main/java/org/apache/geronimo/config/ConfigValueImpl.java b/impl/src/main/java/org/apache/geronimo/config/ConfigValueImpl.java index 90f8884..17ca81a 100644 --- a/impl/src/main/java/org/apache/geronimo/config/ConfigValueImpl.java +++ b/impl/src/main/java/org/apache/geronimo/config/ConfigValueImpl.java @@ -26,9 +26,12 @@ import java.util.concurrent.TimeUnit; import java.util.logging.Logger; +import javax.enterprise.inject.Typed; + /** * @author Mark Struberg */ +@Typed public class ConfigValueImpl implements ConfigValue { private static final Logger logger = Logger.getLogger(ConfigValueImpl.class.getName()); diff --git a/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java b/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java index 0362c73..6aeddf0 100644 --- a/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java +++ b/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java @@ -30,12 +30,15 @@ import java.util.List; import java.util.ServiceLoader; +import javax.enterprise.inject.Typed; + import static java.util.Arrays.asList; /** * @author Romain Manni-Bucau * @author Mark Struberg */ +@Typed public class DefaultConfigBuilder implements ConfigBuilder { protected ClassLoader forClassLoader; private final List sources = new ArrayList<>(); @@ -102,7 +105,7 @@ protected Collection getBuiltInConfigSources(ClassLoader configSources.add(new SystemEnvConfigSource()); configSources.add(new SystemPropertyConfigSource()); - configSources.addAll(new PropertyFileConfigSourceProvider("internal/META-INF/microprofile-config.properties", true, forClassLoader).getConfigSources(forClassLoader)); + configSources.addAll(new PropertyFileConfigSourceProvider("/META-INF/microprofile-config.properties", true, forClassLoader).getConfigSources(forClassLoader)); return configSources; } diff --git a/impl/src/main/java/org/apache/geronimo/config/DefaultConfigProvider.java b/impl/src/main/java/org/apache/geronimo/config/DefaultConfigProvider.java index 09e3767..f28c716 100644 --- a/impl/src/main/java/org/apache/geronimo/config/DefaultConfigProvider.java +++ b/impl/src/main/java/org/apache/geronimo/config/DefaultConfigProvider.java @@ -21,6 +21,9 @@ import java.util.Iterator; import java.util.Map; import java.util.WeakHashMap; + +import javax.enterprise.inject.Typed; + import org.eclipse.microprofile.config.Config; import org.eclipse.microprofile.config.spi.ConfigBuilder; import org.eclipse.microprofile.config.spi.ConfigProviderResolver; @@ -29,6 +32,7 @@ /** * @author Mark Struberg */ +@Typed public class DefaultConfigProvider extends ConfigProviderResolver { private static Map> configs diff --git a/impl/src/main/java/org/apache/geronimo/config/ManualApplicationConfigBuilder.java b/impl/src/main/java/org/apache/geronimo/config/ManualApplicationConfigBuilder.java deleted file mode 100644 index 01ee075..0000000 --- a/impl/src/main/java/org/apache/geronimo/config/ManualApplicationConfigBuilder.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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.geronimo.config; - -import org.eclipse.microprofile.config.Config; -import org.eclipse.microprofile.config.spi.ConfigProviderResolver; - -/** - * @author Mark Struberg - */ -public class ManualApplicationConfigBuilder extends DefaultConfigBuilder { - private DefaultConfigProvider configProvider; - - public ManualApplicationConfigBuilder(DefaultConfigProvider configProvider) { - this.configProvider = configProvider; - } - - @Override - public synchronized Config build() { - Config config = super.build(); - ClassLoader cl = forClassLoader; - if (cl == null) { - cl = Thread.currentThread().getContextClassLoader(); - if (cl == null) { - cl = ConfigProviderResolver.class.getClassLoader(); - } - } - Config oldConfig = configProvider.existingConfig(cl); - if (oldConfig != null) { - throw new IllegalStateException("This Application already has a registered Configuration!"); - } - configProvider.registerConfig(config, cl); - return config; - } -} diff --git a/impl/src/main/java/org/apache/geronimo/config/ConfigInjectionProducer.java b/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionProducer.java similarity index 96% rename from impl/src/main/java/org/apache/geronimo/config/ConfigInjectionProducer.java rename to impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionProducer.java index 049366d..5bd8bb1 100644 --- a/impl/src/main/java/org/apache/geronimo/config/ConfigInjectionProducer.java +++ b/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionProducer.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.geronimo.config; +package org.apache.geronimo.config.cdi; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.inject.Produces; diff --git a/impl/src/test/java/org/apache/geronimo/config/test/GeronimoConfigArchiveProcessor.java b/impl/src/test/java/org/apache/geronimo/config/test/GeronimoConfigArchiveProcessor.java new file mode 100644 index 0000000..7316c01 --- /dev/null +++ b/impl/src/test/java/org/apache/geronimo/config/test/GeronimoConfigArchiveProcessor.java @@ -0,0 +1,56 @@ +/* + * 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.geronimo.config.test; + +import org.apache.geronimo.config.ConfigImpl; +import org.apache.geronimo.config.DefaultConfigProvider; +import org.apache.geronimo.config.cdi.ConfigInjectionProducer; +import org.apache.geronimo.config.configsource.BaseConfigSource; +import org.apache.geronimo.config.converters.BooleanConverter; +import org.eclipse.microprofile.config.spi.ConfigProviderResolver; +import org.jboss.arquillian.container.test.spi.client.deployment.ApplicationArchiveProcessor; +import org.jboss.arquillian.test.spi.TestClass; +import org.jboss.shrinkwrap.api.Archive; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.EmptyAsset; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.jboss.shrinkwrap.api.spec.WebArchive; + +/** + * Adds the whole Config implementation classes and resources to the + * Arqillian deployment archive. This is needed to have the container + * pick up the beans from within the impl for the TCK tests. + * + * @author Mark Struberg + */ +public class GeronimoConfigArchiveProcessor implements ApplicationArchiveProcessor { + + @Override + public void process(Archive applicationArchive, TestClass testClass) { + if (applicationArchive instanceof WebArchive) { + JavaArchive configJar = ShrinkWrap + .create(JavaArchive.class, "geronimo-config-impl.jar") + .addPackage(ConfigImpl.class.getPackage()) + .addPackage(BooleanConverter.class.getPackage()) + .addPackage(BaseConfigSource.class.getPackage()) + .addPackage(ConfigInjectionProducer.class.getPackage()) + .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml") + .addAsServiceProvider(ConfigProviderResolver.class, DefaultConfigProvider.class); + ((WebArchive) applicationArchive).addAsLibraries(configJar); + } + } +} diff --git a/impl/src/test/java/org/apache/geronimo/config/test/GeronimoConfigExtension.java b/impl/src/test/java/org/apache/geronimo/config/test/GeronimoConfigExtension.java new file mode 100644 index 0000000..22335a0 --- /dev/null +++ b/impl/src/test/java/org/apache/geronimo/config/test/GeronimoConfigExtension.java @@ -0,0 +1,30 @@ +/* + * 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.geronimo.config.test; + +import org.jboss.arquillian.container.test.spi.client.deployment.ApplicationArchiveProcessor; +import org.jboss.arquillian.core.spi.LoadableExtension; + +/** + * @author Mark Struberg + */ +public class GeronimoConfigExtension implements LoadableExtension { + @Override + public void register(ExtensionBuilder extensionBuilder) { + extensionBuilder.service(ApplicationArchiveProcessor.class, GeronimoConfigArchiveProcessor.class); + } +} diff --git a/impl/src/test/resources/META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension b/impl/src/test/resources/META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension new file mode 100644 index 0000000..91c04d4 --- /dev/null +++ b/impl/src/test/resources/META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension @@ -0,0 +1,21 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy current the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + + +org.apache.geronimo.config.test.GeronimoConfigExtension \ No newline at end of file From a541df4f7cccf0952b81144e1417d36e1a39644d Mon Sep 17 00:00:00 2001 From: Mark Struberg Date: Wed, 15 Mar 2017 15:25:45 +0100 Subject: [PATCH 21/29] implement CDI support for @ConfigProperty injection --- .../apache/geronimo/config/ConfigImpl.java | 4 +- .../config/cdi/ConfigInjectionBean.java | 195 ++++++++++++++++++ .../config/cdi/ConfigInjectionProducer.java | 12 +- .../config/cdi/ConfigPropertyExtension.java | 63 ++++++ .../config/converters/StringConverter.java | 37 ++++ .../javax.enterprise.inject.spi.Extension | 20 ++ impl/tck-suite.xml | 2 +- 7 files changed, 330 insertions(+), 3 deletions(-) create mode 100644 impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java create mode 100644 impl/src/main/java/org/apache/geronimo/config/cdi/ConfigPropertyExtension.java create mode 100644 impl/src/main/java/org/apache/geronimo/config/converters/StringConverter.java create mode 100644 impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension diff --git a/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java b/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java index 4884ef2..9096988 100644 --- a/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java +++ b/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java @@ -30,6 +30,7 @@ import java.util.logging.Level; import java.util.logging.Logger; +import org.apache.geronimo.config.converters.StringConverter; import org.eclipse.microprofile.config.Config; import org.eclipse.microprofile.config.ConfigValue; import org.eclipse.microprofile.config.spi.ConfigSource; @@ -59,6 +60,7 @@ public ConfigImpl() { } private void registerDefaultConverter() { + converters.put(String.class, StringConverter.INSTANCE); converters.put(Boolean.class, BooleanConverter.INSTANCE); converters.put(Double.class, DoubleConverter.INSTANCE); converters.put(Float.class, FloatConverter.INSTANCE); @@ -98,8 +100,8 @@ public Optional getValue(String key, Class asType) { } public T convert(String value, Class asType) { - Converter converter = getConverter(asType); if (value != null) { + Converter converter = getConverter(asType); return converter.convert(value); } diff --git a/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java b/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java new file mode 100644 index 0000000..17e1a34 --- /dev/null +++ b/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java @@ -0,0 +1,195 @@ +/* + * 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.geronimo.config.cdi; + +import java.lang.annotation.Annotation; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import javax.enterprise.context.Dependent; +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.inject.spi.Annotated; +import javax.enterprise.inject.spi.Bean; +import javax.enterprise.inject.spi.BeanManager; +import javax.enterprise.inject.spi.InjectionPoint; +import javax.enterprise.inject.spi.PassivationCapable; +import javax.enterprise.util.AnnotationLiteral; +import javax.inject.Provider; + +import org.eclipse.microprofile.config.Config; +import org.eclipse.microprofile.config.ConfigProvider; +import org.eclipse.microprofile.config.inject.ConfigProperty; + +/** + * @author Mark Struberg + */ +public class ConfigInjectionBean implements Bean, PassivationCapable { + + private final static Set QUALIFIERS = new HashSet<>(); + static { + QUALIFIERS.add(new ConfigPropertyLiteral()); + } + + private final BeanManager bm; + private final Type type; + private final Class rawType; + private final Set types; + + /** + * only access via {@link #getConfig(} + */ + private Config _config; + + public ConfigInjectionBean(BeanManager bm, Type type) { + this.bm = bm; + this.type = type; + + types = new HashSet<>(); + types.add(type); + rawType = getRawType(type); + } + + private Class getRawType(Type type) { + if (type instanceof Class) { + return (Class) type; + } + else if (type instanceof ParameterizedType) { + ParameterizedType paramType = (ParameterizedType) type; + + return (Class) paramType.getRawType(); + } + + throw new UnsupportedOperationException("No idea how to handle " + type); + } + + @Override + public Set getInjectionPoints() { + return Collections.EMPTY_SET; + } + + @Override + public Class getBeanClass() { + return rawType; + } + + @Override + public boolean isNullable() { + return false; + } + + @Override + public T create(CreationalContext context) { + Set> beans = bm.getBeans(InjectionPoint.class); + Bean bean = bm.resolve(beans); + InjectionPoint ip = (InjectionPoint) bm.getReference(bean, InjectionPoint.class, context); + if (ip == null) { + throw new IllegalStateException("Could not retrieve InjectionPoint"); + } + Annotated annotated = ip.getAnnotated(); + ConfigProperty configProperty = annotated.getAnnotation(ConfigProperty.class); + String key = configProperty.value(); + + if (annotated.getBaseType() instanceof ParameterizedType) { + ParameterizedType paramType = (ParameterizedType) annotated.getBaseType(); + Type rawType = paramType.getRawType(); + if (rawType instanceof Class && ((Class) rawType).isAssignableFrom(Provider.class) && paramType.getActualTypeArguments().length == 1) { + Class clazz = (Class) paramType.getActualTypeArguments()[0]; //X TODO check type again, etc + return (T) new ConfigValueProvider(getConfig(), key, clazz); + } + } + else { + Class clazz = (Class) annotated.getBaseType(); + return (T) getConfig().getValue(key, clazz).orElse(null); + } + + throw new IllegalStateException("unhandled ConfigProperty"); + } + + public Config getConfig() { + if (_config == null) { + _config = ConfigProvider.getConfig(); + } + return _config; + } + + @Override + public void destroy(T instance, CreationalContext context) { + + } + + @Override + public Set getTypes() { + return types; + } + + @Override + public Set getQualifiers() { + return QUALIFIERS; + } + + @Override + public Class getScope() { + return Dependent.class; + } + + @Override + public String getName() { + return null; + } + + @Override + public Set> getStereotypes() { + return Collections.EMPTY_SET; + } + + @Override + public boolean isAlternative() { + return true; + } + + @Override + public String getId() { + return "ConfigInjectionBean_" + rawType.getName(); + } + + private static class ConfigPropertyLiteral extends AnnotationLiteral implements ConfigProperty { + @Override + public String value() { + return ""; + } + } + + public static class ConfigValueProvider implements Provider { + private final Config config; + private final String key; + private Class type; + + ConfigValueProvider(Config config, String key, Class type) { + this.config = config; + this.key = key; + this.type = type; + } + + @Override + public T get() { + return (T) config.getValue(key, type).orElse(null); + } + } +} diff --git a/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionProducer.java b/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionProducer.java index 5bd8bb1..ce16e8e 100644 --- a/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionProducer.java +++ b/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionProducer.java @@ -16,6 +16,8 @@ */ package org.apache.geronimo.config.cdi; + +import javax.annotation.PostConstruct; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.inject.Produces; @@ -28,10 +30,18 @@ @ApplicationScoped public class ConfigInjectionProducer { + private Config config; + + @PostConstruct + void init() { + config = ConfigProvider.getConfig(); + } + @Produces @ApplicationScoped public Config createConfig() { - return ConfigProvider.getConfig(); + return config; } + } diff --git a/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigPropertyExtension.java b/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigPropertyExtension.java new file mode 100644 index 0000000..8633b62 --- /dev/null +++ b/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigPropertyExtension.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.geronimo.config.cdi; + +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; + +import javax.enterprise.event.Observes; +import javax.enterprise.inject.spi.AfterBeanDiscovery; +import javax.enterprise.inject.spi.AfterDeploymentValidation; +import javax.enterprise.inject.spi.BeanManager; +import javax.enterprise.inject.spi.Extension; +import javax.enterprise.inject.spi.InjectionPoint; +import javax.enterprise.inject.spi.ProcessInjectionPoint; +import javax.inject.Provider; + +import org.eclipse.microprofile.config.inject.ConfigProperty; + +/** + * @author Mark Struberg + */ +public class ConfigPropertyExtension implements Extension { + + private Set injectionPoints = new HashSet<>(); + + public void collectConfigProducer(@Observes ProcessInjectionPoint pip) { + ConfigProperty configProperty = pip.getInjectionPoint().getAnnotated().getAnnotation(ConfigProperty.class); + if (configProperty != null) { + injectionPoints.add(pip.getInjectionPoint()); + } + } + + public void registerConfigProducer(@Observes AfterBeanDiscovery abd, BeanManager bm) { + Set types = injectionPoints.stream() + .filter(ip -> ip.getType() instanceof Class) + .map(ip -> (Class) ip.getType()) + .collect(Collectors.toSet()); + + // Provider is a ParameterizedType and not a Class, so we need to add it manually + types.add(Provider.class); + + types.forEach(type -> abd.addBean(new ConfigInjectionBean(bm, type))); + } + + public void validate(@Observes AfterDeploymentValidation add) { + // TODO report any problems + } +} diff --git a/impl/src/main/java/org/apache/geronimo/config/converters/StringConverter.java b/impl/src/main/java/org/apache/geronimo/config/converters/StringConverter.java new file mode 100644 index 0000000..361f805 --- /dev/null +++ b/impl/src/main/java/org/apache/geronimo/config/converters/StringConverter.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.geronimo.config.converters; + +import javax.annotation.Priority; + +import org.eclipse.microprofile.config.spi.Converter; + +/** + * 1:1 string output. Just to make converter logic happy. + * + * @author Mark Struberg + */ +@Priority(1) +public class StringConverter implements Converter { + + public static final StringConverter INSTANCE = new StringConverter(); + + @Override + public String convert(String value) { + return value; + } +} diff --git a/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension b/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension new file mode 100644 index 0000000..7154f81 --- /dev/null +++ b/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension @@ -0,0 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy current the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +org.apache.geronimo.config.cdi.ConfigPropertyExtension \ No newline at end of file diff --git a/impl/tck-suite.xml b/impl/tck-suite.xml index f0033e6..a9fd699 100644 --- a/impl/tck-suite.xml +++ b/impl/tck-suite.xml @@ -17,7 +17,7 @@ --> - + From 83b74e81dc4c4304024609d3753a06cc8cbd4805 Mon Sep 17 00:00:00 2001 From: Mark Struberg Date: Fri, 17 Mar 2017 17:13:11 +0100 Subject: [PATCH 22/29] mp-config-1.0 final API (sic!) still a few behavorial things to clarify, but all tests except 1 are green! --- .../apache/geronimo/config/ConfigImpl.java | 33 +++++++++------ .../geronimo/config/ConfigValueImpl.java | 41 +++++++++++-------- ...rtyExtension.java => ConfigExtension.java} | 8 +++- .../config/cdi/ConfigInjectionBean.java | 39 ++++++++++++++---- .../javax.enterprise.inject.spi.Extension | 2 +- 5 files changed, 82 insertions(+), 41 deletions(-) rename impl/src/main/java/org/apache/geronimo/config/cdi/{ConfigPropertyExtension.java => ConfigExtension.java} (91%) diff --git a/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java b/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java index 9096988..d999ebe 100644 --- a/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java +++ b/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java @@ -25,6 +25,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.NoSuchElementException; import java.util.Optional; import java.util.Set; import java.util.logging.Level; @@ -32,7 +33,6 @@ import org.apache.geronimo.config.converters.StringConverter; import org.eclipse.microprofile.config.Config; -import org.eclipse.microprofile.config.ConfigValue; import org.eclipse.microprofile.config.spi.ConfigSource; import org.eclipse.microprofile.config.spi.Converter; import org.apache.geronimo.config.converters.BooleanConverter; @@ -68,13 +68,25 @@ private void registerDefaultConverter() { converters.put(Long.class, LongConverter.INSTANCE); } + + @Override + public Optional getOptionalValue(String propertyName, Class asType) { + String value = getValue(propertyName); + if (value != null && value.length() == 0) { + // treat an empty string as not existing + value = null; + } + return Optional.ofNullable(convert(value, asType)); + } + @Override - public Optional getString(String key) { - String val = getValue(key); - if (val == null || val.isEmpty()) { - return Optional.empty(); + public T getValue(String propertyName, Class propertyType) { + String value = getValue(propertyName); + if (value == null || value.length() == 0) { + throw new NoSuchElementException("No configured value found for config key " + propertyName); } - return Optional.ofNullable(val); + + return convert(value, propertyType); } public String getValue(String key) { @@ -90,13 +102,8 @@ public String getValue(String key) { return value; } } - return null; - } - @Override - public Optional getValue(String key, Class asType) { - String value = getValue(key); - return Optional.ofNullable(convert(value, asType)); + return null; } public T convert(String value, Class asType) { @@ -116,7 +123,7 @@ private Converter getConverter(Class asType) { return converter; } - public ConfigValue access(String key) { + public ConfigValueImpl access(String key) { return new ConfigValueImpl(this, key); } diff --git a/impl/src/main/java/org/apache/geronimo/config/ConfigValueImpl.java b/impl/src/main/java/org/apache/geronimo/config/ConfigValueImpl.java index 17ca81a..b88a0ff 100644 --- a/impl/src/main/java/org/apache/geronimo/config/ConfigValueImpl.java +++ b/impl/src/main/java/org/apache/geronimo/config/ConfigValueImpl.java @@ -16,7 +16,6 @@ */ package org.apache.geronimo.config; -import org.eclipse.microprofile.config.ConfigValue; import org.eclipse.microprofile.config.spi.Converter; import java.util.ArrayList; @@ -32,7 +31,7 @@ * @author Mark Struberg */ @Typed -public class ConfigValueImpl implements ConfigValue { +public class ConfigValueImpl { private static final Logger logger = Logger.getLogger(ConfigValueImpl.class.getName()); private final ConfigImpl config; @@ -57,31 +56,31 @@ public ConfigValueImpl(ConfigImpl config, String key) { this.keyOriginal = key; } - @Override - public ConfigValue as(Class clazz) { + //X @Override + public ConfigValueImpl as(Class clazz) { configEntryType = clazz; - return (ConfigValue) this; + return (ConfigValueImpl) this; } - @Override - public ConfigValue cacheFor(long value, TimeUnit timeUnit) { + //X @Override + public ConfigValueImpl cacheFor(long value, TimeUnit timeUnit) { this.cacheTimeMs = timeUnit.toMillis(value); return this; } - @Override - public ConfigValue evaluateVariables(boolean evaluateVariables) { + //X @Override + public ConfigValueImpl evaluateVariables(boolean evaluateVariables) { this.evaluateVariables = evaluateVariables; return this; } - public ConfigValue withLookupChain(String... postfixNames) { + public ConfigValueImpl withLookupChain(String... postfixNames) { this.lookupChain = postfixNames; return this; } - @Override + //X @Override public T get() { T val = getValue(); if (val == null) { @@ -90,18 +89,18 @@ public T get() { return val; } - @Override + //X @Override public Optional getOptional() { return Optional.ofNullable(getValue()); } - @Override - public ConfigValue onChange(ConfigChanged valueChangeListener) { + //X @Override + public ConfigValueImpl onChange(ConfigChanged valueChangeListener) { this.valueChangeListener = valueChangeListener; return this; } - @Override + //X @Override public List getValueList() { String rawList = (String) getValue(false); List values = new ArrayList(); @@ -205,12 +204,12 @@ private String resolveStringValue() { return value; } - @Override + //X @Override public String getKey() { return keyOriginal; } - @Override + //X @Override public String getResolvedKey() { return keyResolved; } @@ -228,4 +227,12 @@ private T convert(String value) { return (T) converter.convert(value); } + /** + * TODO feedback from gunnar: could be interesting to have this functionality also as Config#onChange(ConfigChanged) + * Callback which can be used with {@link #onChange(ConfigChanged)} + */ + interface ConfigChanged { + void onValueChange(String key, T oldValue, T newValue); + } + } diff --git a/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigPropertyExtension.java b/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java similarity index 91% rename from impl/src/main/java/org/apache/geronimo/config/cdi/ConfigPropertyExtension.java rename to impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java index 8633b62..0d8f43f 100644 --- a/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigPropertyExtension.java +++ b/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java @@ -24,6 +24,7 @@ import javax.enterprise.inject.spi.AfterBeanDiscovery; import javax.enterprise.inject.spi.AfterDeploymentValidation; import javax.enterprise.inject.spi.BeanManager; +import javax.enterprise.inject.spi.BeforeShutdown; import javax.enterprise.inject.spi.Extension; import javax.enterprise.inject.spi.InjectionPoint; import javax.enterprise.inject.spi.ProcessInjectionPoint; @@ -34,7 +35,7 @@ /** * @author Mark Struberg */ -public class ConfigPropertyExtension implements Extension { +public class ConfigExtension implements Extension { private Set injectionPoints = new HashSet<>(); @@ -59,5 +60,10 @@ public void registerConfigProducer(@Observes AfterBeanDiscovery abd, BeanManager public void validate(@Observes AfterDeploymentValidation add) { // TODO report any problems + //X injectionPoints.forEach(); + } + + public void shutdown(@Observes BeforeShutdown bsd) { + //X TODO shutdown config } } diff --git a/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java b/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java index 17e1a34..db19583 100644 --- a/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java +++ b/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java @@ -16,11 +16,14 @@ */ package org.apache.geronimo.config.cdi; +import java.io.IOException; +import java.io.Serializable; import java.lang.annotation.Annotation; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Collections; import java.util.HashSet; +import java.util.Optional; import java.util.Set; import javax.enterprise.context.Dependent; @@ -36,6 +39,7 @@ import org.eclipse.microprofile.config.Config; import org.eclipse.microprofile.config.ConfigProvider; import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.eclipse.microprofile.config.spi.ConfigProviderResolver; /** * @author Mark Struberg @@ -48,7 +52,6 @@ public class ConfigInjectionBean implements Bean, PassivationCapable { } private final BeanManager bm; - private final Type type; private final Class rawType; private final Set types; @@ -59,7 +62,6 @@ public class ConfigInjectionBean implements Bean, PassivationCapable { public ConfigInjectionBean(BeanManager bm, Type type) { this.bm = bm; - this.type = type; types = new HashSet<>(); types.add(type); @@ -104,19 +106,27 @@ public T create(CreationalContext context) { } Annotated annotated = ip.getAnnotated(); ConfigProperty configProperty = annotated.getAnnotation(ConfigProperty.class); - String key = configProperty.value(); + String key = configProperty.name(); if (annotated.getBaseType() instanceof ParameterizedType) { ParameterizedType paramType = (ParameterizedType) annotated.getBaseType(); Type rawType = paramType.getRawType(); + + // handle Provider if (rawType instanceof Class && ((Class) rawType).isAssignableFrom(Provider.class) && paramType.getActualTypeArguments().length == 1) { Class clazz = (Class) paramType.getActualTypeArguments()[0]; //X TODO check type again, etc return (T) new ConfigValueProvider(getConfig(), key, clazz); } + + // handle Optional + if (rawType instanceof Class && ((Class) rawType).isAssignableFrom(Optional.class) && paramType.getActualTypeArguments().length == 1) { + Class clazz = (Class) paramType.getActualTypeArguments()[0]; //X TODO check type again, etc + return (T) getConfig().getOptionalValue(key, clazz); + } } else { Class clazz = (Class) annotated.getBaseType(); - return (T) getConfig().getValue(key, clazz).orElse(null); + return (T) getConfig().getValue(key, clazz); } throw new IllegalStateException("unhandled ConfigProperty"); @@ -171,15 +181,20 @@ public String getId() { private static class ConfigPropertyLiteral extends AnnotationLiteral implements ConfigProperty { @Override - public String value() { + public String name() { + return ""; + } + + @Override + public String defaultValue() { return ""; } } - public static class ConfigValueProvider implements Provider { - private final Config config; + public static class ConfigValueProvider implements Provider, Serializable { + private transient Config config; private final String key; - private Class type; + private final Class type; ConfigValueProvider(Config config, String key, Class type) { this.config = config; @@ -189,7 +204,13 @@ public static class ConfigValueProvider implements Provider { @Override public T get() { - return (T) config.getValue(key, type).orElse(null); + return (T) config.getValue(key, type); } + + private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + config = ConfigProviderResolver.instance().getConfig(); + } + } } diff --git a/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension b/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension index 7154f81..f949a49 100644 --- a/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension +++ b/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension @@ -17,4 +17,4 @@ # under the License. # -org.apache.geronimo.config.cdi.ConfigPropertyExtension \ No newline at end of file +org.apache.geronimo.config.cdi.ConfigExtension \ No newline at end of file From 4fcec6469e9e725ab35b6c294bcbe23837ce0ed3 Mon Sep 17 00:00:00 2001 From: Mark Struberg Date: Fri, 17 Mar 2017 23:11:33 +0100 Subject: [PATCH 23/29] fix config file name --- README.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.adoc b/README.adoc index 5f6c584..3a083aa 100644 --- a/README.adoc +++ b/README.adoc @@ -47,9 +47,9 @@ By default there are 3 default ConfigSources: * `System.getenv()` (ordinal=400) * `System.getProperties()` (ordinal=300) -* all `META-INF/java-config.properties` files on the ClassPath. (ordinal=100, separately configurable via a config_ordinal property inside each file) +* all `META-INF/microprofile-config.properties` files on the ClassPath. (ordinal=100, separately configurable via a config_ordinal property inside each file) -That means that I can put my default configuration in a `META-INF/java-config.properties` anywhere on the classpath. +That means that I can put my default configuration in a `META-INF/microprofile-config.properties` anywhere on the classpath. And I can later simply e.g set a system property to change this default configuration. == Custom ConfigSources From bf81b6e4055febb069cd01c30b2aeeaad40de7ac Mon Sep 17 00:00:00 2001 From: Mark Struberg Date: Tue, 21 Mar 2017 00:01:34 +0100 Subject: [PATCH 24/29] add check for missing properties during bootstrap. WIP, still a few rules missing --- impl/debug-suite.xml | 2 +- .../geronimo/config/cdi/ConfigExtension.java | 32 +++++++++++++++-- .../config/cdi/ConfigInjectionBean.java | 34 +++++++++++++++++++ 3 files changed, 65 insertions(+), 3 deletions(-) diff --git a/impl/debug-suite.xml b/impl/debug-suite.xml index 10e8976..8269c26 100644 --- a/impl/debug-suite.xml +++ b/impl/debug-suite.xml @@ -24,7 +24,7 @@ - + diff --git a/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java b/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java index 0d8f43f..aee891d 100644 --- a/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java +++ b/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java @@ -16,7 +16,10 @@ */ package org.apache.geronimo.config.cdi; +import java.lang.reflect.Type; +import java.util.ArrayList; import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -25,11 +28,14 @@ import javax.enterprise.inject.spi.AfterDeploymentValidation; import javax.enterprise.inject.spi.BeanManager; import javax.enterprise.inject.spi.BeforeShutdown; +import javax.enterprise.inject.spi.DeploymentException; import javax.enterprise.inject.spi.Extension; import javax.enterprise.inject.spi.InjectionPoint; import javax.enterprise.inject.spi.ProcessInjectionPoint; import javax.inject.Provider; +import org.eclipse.microprofile.config.Config; +import org.eclipse.microprofile.config.ConfigProvider; import org.eclipse.microprofile.config.inject.ConfigProperty; /** @@ -59,11 +65,33 @@ public void registerConfigProducer(@Observes AfterBeanDiscovery abd, BeanManager } public void validate(@Observes AfterDeploymentValidation add) { - // TODO report any problems - //X injectionPoints.forEach(); + List deploymentProblems = new ArrayList<>(); + + Config config = ConfigProvider.getConfig(); + + for (InjectionPoint injectionPoint : injectionPoints) { + Type type = injectionPoint.getType(); + ConfigProperty configProperty = injectionPoint.getAnnotated().getAnnotation(ConfigProperty.class); + if (type instanceof Class) { + // a direct injection of a ConfigProperty + // that means a Converter must exist. + String key = ConfigInjectionBean.getConfigKey(injectionPoint, configProperty); + if (!config.getOptionalValue(key, (Class) type).isPresent()) { + deploymentProblems.add("No Config Value exists for " + key); + } + } + } + + if (!deploymentProblems.isEmpty()) { + add.addDeploymentProblem(new DeploymentException("Error while validating Configuration\n" + + String.join("\n", deploymentProblems))); + } + } public void shutdown(@Observes BeforeShutdown bsd) { //X TODO shutdown config } + + } diff --git a/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java b/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java index db19583..ba2b39b 100644 --- a/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java +++ b/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java @@ -29,8 +29,11 @@ import javax.enterprise.context.Dependent; import javax.enterprise.context.spi.CreationalContext; import javax.enterprise.inject.spi.Annotated; +import javax.enterprise.inject.spi.AnnotatedMember; +import javax.enterprise.inject.spi.AnnotatedType; import javax.enterprise.inject.spi.Bean; import javax.enterprise.inject.spi.BeanManager; +import javax.enterprise.inject.spi.DeploymentException; import javax.enterprise.inject.spi.InjectionPoint; import javax.enterprise.inject.spi.PassivationCapable; import javax.enterprise.util.AnnotationLiteral; @@ -132,6 +135,37 @@ public T create(CreationalContext context) { throw new IllegalStateException("unhandled ConfigProperty"); } + + /** + * Get the property key to use. + * In case the {@link ConfigProperty#name()} is empty we will try to determine the key name from the InjectionPoint. + */ + public static String getConfigKey(InjectionPoint ip, ConfigProperty configProperty) { + String key = configProperty.name(); + if (key.length() > 0) { + return key; + } + if (ip.getAnnotated() instanceof AnnotatedMember) { + AnnotatedMember member = (AnnotatedMember) ip.getAnnotated(); + AnnotatedType declaringType = member.getDeclaringType(); + if (declaringType != null) { + String[] parts = declaringType.getJavaClass().getName().split("."); + String cn = parts[parts.length-1]; + parts[parts.length-1] = Character.toLowerCase(cn.charAt(0)) + (cn.length() > 1 ? cn.substring(1) : ""); + StringBuilder sb = new StringBuilder(parts[0]); + for (int i = 1; i < parts.length; i++) { + sb.append(".").append(parts[i]); + } + + // now add the field name + sb.append(".").append(member.getJavaMember().getName()); + return sb.toString(); + } + } + + throw new IllegalStateException("Could not find default name for @ConfigProperty InjectionPoint " + ip); + } + public Config getConfig() { if (_config == null) { _config = ConfigProvider.getConfig(); From 77b1c699fc7feb5af4d1aa445270acfea2eb08bb Mon Sep 17 00:00:00 2001 From: Mark Struberg Date: Tue, 21 Mar 2017 22:06:47 +0100 Subject: [PATCH 25/29] fix optional and prevent internal classes as Beans --- impl/debug-suite.xml | 2 +- .../src/main/java/org/apache/geronimo/config/ConfigImpl.java | 2 ++ .../org/apache/geronimo/config/DefaultConfigBuilder.java | 2 ++ .../org/apache/geronimo/config/DefaultConfigProvider.java | 2 ++ .../java/org/apache/geronimo/config/cdi/ConfigExtension.java | 4 +++- .../config/configsource/PropertyFileConfigSource.java | 5 +++++ .../configsource/PropertyFileConfigSourceProvider.java | 5 +++++ .../geronimo/config/configsource/SystemEnvConfigSource.java | 5 +++++ .../config/configsource/SystemPropertyConfigSource.java | 5 +++++ .../apache/geronimo/config/converters/BooleanConverter.java | 2 ++ .../apache/geronimo/config/converters/DoubleConverter.java | 2 ++ .../apache/geronimo/config/converters/FloatConverter.java | 2 ++ .../apache/geronimo/config/converters/IntegerConverter.java | 2 ++ .../org/apache/geronimo/config/converters/LongConverter.java | 2 ++ .../apache/geronimo/config/converters/StringConverter.java | 2 ++ 15 files changed, 42 insertions(+), 2 deletions(-) diff --git a/impl/debug-suite.xml b/impl/debug-suite.xml index 8269c26..cc92112 100644 --- a/impl/debug-suite.xml +++ b/impl/debug-suite.xml @@ -24,7 +24,7 @@ - + diff --git a/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java b/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java index d999ebe..7d6e971 100644 --- a/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java +++ b/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java @@ -43,11 +43,13 @@ import javax.annotation.Priority; import javax.enterprise.inject.Typed; +import javax.enterprise.inject.Vetoed; /** * @author Mark Struberg */ @Typed +@Vetoed public class ConfigImpl implements Config { protected Logger logger = Logger.getLogger(ConfigImpl.class.getName()); diff --git a/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java b/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java index 6aeddf0..a61760f 100644 --- a/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java +++ b/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java @@ -31,6 +31,7 @@ import java.util.ServiceLoader; import javax.enterprise.inject.Typed; +import javax.enterprise.inject.Vetoed; import static java.util.Arrays.asList; @@ -39,6 +40,7 @@ * @author Mark Struberg */ @Typed +@Vetoed public class DefaultConfigBuilder implements ConfigBuilder { protected ClassLoader forClassLoader; private final List sources = new ArrayList<>(); diff --git a/impl/src/main/java/org/apache/geronimo/config/DefaultConfigProvider.java b/impl/src/main/java/org/apache/geronimo/config/DefaultConfigProvider.java index f28c716..d8a655f 100644 --- a/impl/src/main/java/org/apache/geronimo/config/DefaultConfigProvider.java +++ b/impl/src/main/java/org/apache/geronimo/config/DefaultConfigProvider.java @@ -23,6 +23,7 @@ import java.util.WeakHashMap; import javax.enterprise.inject.Typed; +import javax.enterprise.inject.Vetoed; import org.eclipse.microprofile.config.Config; import org.eclipse.microprofile.config.spi.ConfigBuilder; @@ -33,6 +34,7 @@ * @author Mark Struberg */ @Typed +@Vetoed public class DefaultConfigProvider extends ConfigProviderResolver { private static Map> configs diff --git a/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java b/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java index aee891d..f22e8b5 100644 --- a/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java +++ b/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -58,8 +59,9 @@ public void registerConfigProducer(@Observes AfterBeanDiscovery abd, BeanManager .map(ip -> (Class) ip.getType()) .collect(Collectors.toSet()); - // Provider is a ParameterizedType and not a Class, so we need to add it manually + // Provider and Optional are ParameterizedTypes and not a Class, so we need to add them manually types.add(Provider.class); + types.add(Optional.class); types.forEach(type -> abd.addBean(new ConfigInjectionBean(bm, type))); } diff --git a/impl/src/main/java/org/apache/geronimo/config/configsource/PropertyFileConfigSource.java b/impl/src/main/java/org/apache/geronimo/config/configsource/PropertyFileConfigSource.java index 7d86394..e7c0b2c 100644 --- a/impl/src/main/java/org/apache/geronimo/config/configsource/PropertyFileConfigSource.java +++ b/impl/src/main/java/org/apache/geronimo/config/configsource/PropertyFileConfigSource.java @@ -22,9 +22,14 @@ import java.util.Map; import java.util.Properties; +import javax.enterprise.inject.Typed; +import javax.enterprise.inject.Vetoed; + /** * @author Mark Struberg */ +@Typed +@Vetoed public class PropertyFileConfigSource extends BaseConfigSource { private Map properties; private String fileName; diff --git a/impl/src/main/java/org/apache/geronimo/config/configsource/PropertyFileConfigSourceProvider.java b/impl/src/main/java/org/apache/geronimo/config/configsource/PropertyFileConfigSourceProvider.java index f4be5fa..abbf199 100644 --- a/impl/src/main/java/org/apache/geronimo/config/configsource/PropertyFileConfigSourceProvider.java +++ b/impl/src/main/java/org/apache/geronimo/config/configsource/PropertyFileConfigSourceProvider.java @@ -26,6 +26,9 @@ import java.util.logging.Level; import java.util.logging.Logger; +import javax.enterprise.inject.Typed; +import javax.enterprise.inject.Vetoed; + import org.eclipse.microprofile.config.spi.ConfigSource; import org.eclipse.microprofile.config.spi.ConfigSourceProvider; @@ -36,6 +39,8 @@ * * @author Mark Struberg */ +@Typed +@Vetoed public class PropertyFileConfigSourceProvider implements ConfigSourceProvider { private static final Logger LOG = Logger.getLogger(PropertyFileConfigSourceProvider.class.getName()); diff --git a/impl/src/main/java/org/apache/geronimo/config/configsource/SystemEnvConfigSource.java b/impl/src/main/java/org/apache/geronimo/config/configsource/SystemEnvConfigSource.java index 1c31cc6..6eefca5 100644 --- a/impl/src/main/java/org/apache/geronimo/config/configsource/SystemEnvConfigSource.java +++ b/impl/src/main/java/org/apache/geronimo/config/configsource/SystemEnvConfigSource.java @@ -21,6 +21,9 @@ import java.util.Map; +import javax.enterprise.inject.Typed; +import javax.enterprise.inject.Vetoed; + import org.eclipse.microprofile.config.spi.ConfigSource; /** @@ -31,6 +34,8 @@ * * @author Mark Struberg */ +@Typed +@Vetoed public class SystemEnvConfigSource extends BaseConfigSource { private Map configValues; diff --git a/impl/src/main/java/org/apache/geronimo/config/configsource/SystemPropertyConfigSource.java b/impl/src/main/java/org/apache/geronimo/config/configsource/SystemPropertyConfigSource.java index f5f8ea1..4d741bd 100644 --- a/impl/src/main/java/org/apache/geronimo/config/configsource/SystemPropertyConfigSource.java +++ b/impl/src/main/java/org/apache/geronimo/config/configsource/SystemPropertyConfigSource.java @@ -20,6 +20,9 @@ import java.util.Map; +import javax.enterprise.inject.Typed; +import javax.enterprise.inject.Vetoed; + import org.eclipse.microprofile.config.spi.ConfigSource; /** @@ -27,6 +30,8 @@ * * @author Mark Struberg */ +@Typed +@Vetoed public class SystemPropertyConfigSource extends BaseConfigSource { public SystemPropertyConfigSource() { initOrdinal(400); diff --git a/impl/src/main/java/org/apache/geronimo/config/converters/BooleanConverter.java b/impl/src/main/java/org/apache/geronimo/config/converters/BooleanConverter.java index e2b5d3c..e004870 100644 --- a/impl/src/main/java/org/apache/geronimo/config/converters/BooleanConverter.java +++ b/impl/src/main/java/org/apache/geronimo/config/converters/BooleanConverter.java @@ -19,11 +19,13 @@ import org.eclipse.microprofile.config.spi.Converter; import javax.annotation.Priority; +import javax.enterprise.inject.Vetoed; /** * @author Mark Struberg */ @Priority(1) +@Vetoed public class BooleanConverter implements Converter { public static final BooleanConverter INSTANCE = new BooleanConverter(); diff --git a/impl/src/main/java/org/apache/geronimo/config/converters/DoubleConverter.java b/impl/src/main/java/org/apache/geronimo/config/converters/DoubleConverter.java index c1eb6fb..28cd9f8 100644 --- a/impl/src/main/java/org/apache/geronimo/config/converters/DoubleConverter.java +++ b/impl/src/main/java/org/apache/geronimo/config/converters/DoubleConverter.java @@ -19,11 +19,13 @@ import org.eclipse.microprofile.config.spi.Converter; import javax.annotation.Priority; +import javax.enterprise.inject.Vetoed; /** * @author Mark Struberg */ @Priority(1) +@Vetoed public class DoubleConverter implements Converter { public static final DoubleConverter INSTANCE = new DoubleConverter(); diff --git a/impl/src/main/java/org/apache/geronimo/config/converters/FloatConverter.java b/impl/src/main/java/org/apache/geronimo/config/converters/FloatConverter.java index 1a4eaac..94c14d7 100644 --- a/impl/src/main/java/org/apache/geronimo/config/converters/FloatConverter.java +++ b/impl/src/main/java/org/apache/geronimo/config/converters/FloatConverter.java @@ -17,6 +17,7 @@ package org.apache.geronimo.config.converters; import javax.annotation.Priority; +import javax.enterprise.inject.Vetoed; import org.eclipse.microprofile.config.spi.Converter; @@ -24,6 +25,7 @@ * @author Mark Struberg */ @Priority(1) +@Vetoed public class FloatConverter implements Converter { public static final FloatConverter INSTANCE = new FloatConverter(); diff --git a/impl/src/main/java/org/apache/geronimo/config/converters/IntegerConverter.java b/impl/src/main/java/org/apache/geronimo/config/converters/IntegerConverter.java index be32e8a..d34c468 100644 --- a/impl/src/main/java/org/apache/geronimo/config/converters/IntegerConverter.java +++ b/impl/src/main/java/org/apache/geronimo/config/converters/IntegerConverter.java @@ -17,6 +17,7 @@ package org.apache.geronimo.config.converters; import javax.annotation.Priority; +import javax.enterprise.inject.Vetoed; import org.eclipse.microprofile.config.spi.Converter; @@ -24,6 +25,7 @@ * @author Mark Struberg */ @Priority(1) +@Vetoed public class IntegerConverter implements Converter { public static final IntegerConverter INSTANCE = new IntegerConverter(); diff --git a/impl/src/main/java/org/apache/geronimo/config/converters/LongConverter.java b/impl/src/main/java/org/apache/geronimo/config/converters/LongConverter.java index dc63f5a..007d1c7 100644 --- a/impl/src/main/java/org/apache/geronimo/config/converters/LongConverter.java +++ b/impl/src/main/java/org/apache/geronimo/config/converters/LongConverter.java @@ -19,11 +19,13 @@ import org.eclipse.microprofile.config.spi.Converter; import javax.annotation.Priority; +import javax.enterprise.inject.Vetoed; /** * @author Mark Struberg */ @Priority(1) +@Vetoed public class LongConverter implements Converter { public static final LongConverter INSTANCE = new LongConverter(); diff --git a/impl/src/main/java/org/apache/geronimo/config/converters/StringConverter.java b/impl/src/main/java/org/apache/geronimo/config/converters/StringConverter.java index 361f805..0d5ccbc 100644 --- a/impl/src/main/java/org/apache/geronimo/config/converters/StringConverter.java +++ b/impl/src/main/java/org/apache/geronimo/config/converters/StringConverter.java @@ -17,6 +17,7 @@ package org.apache.geronimo.config.converters; import javax.annotation.Priority; +import javax.enterprise.inject.Vetoed; import org.eclipse.microprofile.config.spi.Converter; @@ -26,6 +27,7 @@ * @author Mark Struberg */ @Priority(1) +@Vetoed public class StringConverter implements Converter { public static final StringConverter INSTANCE = new StringConverter(); From 4ca5f0936a96f04623a585be33608f29247b8071 Mon Sep 17 00:00:00 2001 From: Mark Struberg Date: Fri, 24 Mar 2017 13:24:44 +0100 Subject: [PATCH 26/29] add various Java8 Time api converters --- impl/debug-suite.xml | 2 +- .../apache/geronimo/config/ConfigImpl.java | 13 +++++ .../config/converters/BooleanConverter.java | 1 + .../config/converters/DurationConverter.java | 48 +++++++++++++++++++ .../config/converters/LocalDateConverter.java | 48 +++++++++++++++++++ .../converters/LocalDateTimeConverter.java | 48 +++++++++++++++++++ .../config/converters/LocalTimeConverter.java | 48 +++++++++++++++++++ 7 files changed, 207 insertions(+), 1 deletion(-) create mode 100644 impl/src/main/java/org/apache/geronimo/config/converters/DurationConverter.java create mode 100644 impl/src/main/java/org/apache/geronimo/config/converters/LocalDateConverter.java create mode 100644 impl/src/main/java/org/apache/geronimo/config/converters/LocalDateTimeConverter.java create mode 100644 impl/src/main/java/org/apache/geronimo/config/converters/LocalTimeConverter.java diff --git a/impl/debug-suite.xml b/impl/debug-suite.xml index cc92112..b121bee 100644 --- a/impl/debug-suite.xml +++ b/impl/debug-suite.xml @@ -24,7 +24,7 @@ - + diff --git a/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java b/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java index 7d6e971..f2ab338 100644 --- a/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java +++ b/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java @@ -18,6 +18,10 @@ import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; +import java.time.Duration; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -31,6 +35,10 @@ import java.util.logging.Level; import java.util.logging.Logger; +import org.apache.geronimo.config.converters.DurationConverter; +import org.apache.geronimo.config.converters.LocalDateConverter; +import org.apache.geronimo.config.converters.LocalDateTimeConverter; +import org.apache.geronimo.config.converters.LocalTimeConverter; import org.apache.geronimo.config.converters.StringConverter; import org.eclipse.microprofile.config.Config; import org.eclipse.microprofile.config.spi.ConfigSource; @@ -68,6 +76,11 @@ private void registerDefaultConverter() { converters.put(Float.class, FloatConverter.INSTANCE); converters.put(Integer.class, IntegerConverter.INSTANCE); converters.put(Long.class, LongConverter.INSTANCE); + + converters.put(Duration.class, DurationConverter.INSTANCE); + converters.put(LocalTime.class, LocalTimeConverter.INSTANCE); + converters.put(LocalDate.class, LocalDateConverter.INSTANCE); + converters.put(LocalDateTime.class, LocalDateTimeConverter.INSTANCE); } diff --git a/impl/src/main/java/org/apache/geronimo/config/converters/BooleanConverter.java b/impl/src/main/java/org/apache/geronimo/config/converters/BooleanConverter.java index e004870..9f70a33 100644 --- a/impl/src/main/java/org/apache/geronimo/config/converters/BooleanConverter.java +++ b/impl/src/main/java/org/apache/geronimo/config/converters/BooleanConverter.java @@ -37,6 +37,7 @@ public Boolean convert(String value) { || "1".equalsIgnoreCase(value) || "YES".equalsIgnoreCase(value) || "Y".equalsIgnoreCase(value) + || "ON".equalsIgnoreCase(value) || "JA".equalsIgnoreCase(value) || "J".equalsIgnoreCase(value) || "OUI".equalsIgnoreCase(value); diff --git a/impl/src/main/java/org/apache/geronimo/config/converters/DurationConverter.java b/impl/src/main/java/org/apache/geronimo/config/converters/DurationConverter.java new file mode 100644 index 0000000..8f04abb --- /dev/null +++ b/impl/src/main/java/org/apache/geronimo/config/converters/DurationConverter.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.geronimo.config.converters; + +import java.time.Duration; +import java.time.format.DateTimeParseException; + +import javax.annotation.Priority; +import javax.enterprise.inject.Vetoed; + +import org.eclipse.microprofile.config.spi.Converter; + +/** + * @author Mark Struberg + */ +@Priority(1) +@Vetoed +public class DurationConverter implements Converter { + + public static final DurationConverter INSTANCE = new DurationConverter(); + + @Override + public Duration convert(String value) { + if (value != null) { + try { + return Duration.parse(value); + } + catch (DateTimeParseException dtpe) { + throw new IllegalArgumentException(dtpe); + } + } + return null; + } +} diff --git a/impl/src/main/java/org/apache/geronimo/config/converters/LocalDateConverter.java b/impl/src/main/java/org/apache/geronimo/config/converters/LocalDateConverter.java new file mode 100644 index 0000000..41b9968 --- /dev/null +++ b/impl/src/main/java/org/apache/geronimo/config/converters/LocalDateConverter.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.geronimo.config.converters; + +import java.time.LocalDate; +import java.time.format.DateTimeParseException; + +import javax.annotation.Priority; +import javax.enterprise.inject.Vetoed; + +import org.eclipse.microprofile.config.spi.Converter; + +/** + * @author Mark Struberg + */ +@Priority(1) +@Vetoed +public class LocalDateConverter implements Converter { + + public static final LocalDateConverter INSTANCE = new LocalDateConverter(); + + @Override + public LocalDate convert(String value) { + if (value != null) { + try { + return LocalDate.parse(value); + } + catch (DateTimeParseException dtpe) { + throw new IllegalArgumentException(dtpe); + } + } + return null; + } +} diff --git a/impl/src/main/java/org/apache/geronimo/config/converters/LocalDateTimeConverter.java b/impl/src/main/java/org/apache/geronimo/config/converters/LocalDateTimeConverter.java new file mode 100644 index 0000000..fe5c09e --- /dev/null +++ b/impl/src/main/java/org/apache/geronimo/config/converters/LocalDateTimeConverter.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.geronimo.config.converters; + +import java.time.LocalDateTime; +import java.time.format.DateTimeParseException; + +import javax.annotation.Priority; +import javax.enterprise.inject.Vetoed; + +import org.eclipse.microprofile.config.spi.Converter; + +/** + * @author Mark Struberg + */ +@Priority(1) +@Vetoed +public class LocalDateTimeConverter implements Converter { + + public static final LocalDateTimeConverter INSTANCE = new LocalDateTimeConverter(); + + @Override + public LocalDateTime convert(String value) { + if (value != null) { + try { + return LocalDateTime.parse(value); + } + catch (DateTimeParseException dtpe) { + throw new IllegalArgumentException(dtpe); + } + } + return null; + } +} diff --git a/impl/src/main/java/org/apache/geronimo/config/converters/LocalTimeConverter.java b/impl/src/main/java/org/apache/geronimo/config/converters/LocalTimeConverter.java new file mode 100644 index 0000000..326c167 --- /dev/null +++ b/impl/src/main/java/org/apache/geronimo/config/converters/LocalTimeConverter.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.geronimo.config.converters; + +import java.time.LocalTime; +import java.time.format.DateTimeParseException; + +import javax.annotation.Priority; +import javax.enterprise.inject.Vetoed; + +import org.eclipse.microprofile.config.spi.Converter; + +/** + * @author Mark Struberg + */ +@Priority(1) +@Vetoed +public class LocalTimeConverter implements Converter { + + public static final LocalTimeConverter INSTANCE = new LocalTimeConverter(); + + @Override + public LocalTime convert(String value) { + if (value != null) { + try { + return LocalTime.parse(value); + } + catch (DateTimeParseException dtpe) { + throw new IllegalArgumentException(dtpe); + } + } + return null; + } +} From 372c08979218afd60e886175b77b842f1eb74563 Mon Sep 17 00:00:00 2001 From: Mark Struberg Date: Sat, 8 Apr 2017 00:38:10 +0200 Subject: [PATCH 27/29] fix Config cleanup at shutdown and implement new method --- NOTICE | 2 +- .../geronimo/config/DefaultConfigBuilder.java | 15 ++++++++++++++- .../geronimo/config/DefaultConfigProvider.java | 18 ++++++++++++------ .../geronimo/config/cdi/ConfigExtension.java | 7 +++++-- 4 files changed, 32 insertions(+), 10 deletions(-) diff --git a/NOTICE b/NOTICE index 451c174..4571a01 100644 --- a/NOTICE +++ b/NOTICE @@ -1,4 +1,4 @@ -Copyright 2016-2017 original author and authors +Copyright 2009-2017 original author and authors This product includes software developed at The Apache Software Foundation (http://www.apache.org/). \ No newline at end of file diff --git a/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java b/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java index a61760f..ad56326 100644 --- a/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java +++ b/impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java @@ -46,6 +46,7 @@ public class DefaultConfigBuilder implements ConfigBuilder { private final List sources = new ArrayList<>(); private final List> converters = new ArrayList<>(); private boolean ignoreDefaultSources = true; + private boolean ignoreDiscoveredSources = true; @Override public ConfigBuilder addDefaultSources() { @@ -53,6 +54,12 @@ public ConfigBuilder addDefaultSources() { return this; } + @Override + public ConfigBuilder addDiscoveredSources() { + this.ignoreDiscoveredSources = false; + return this; + } + @Override public ConfigBuilder forClassLoader(final ClassLoader loader) { this.forClassLoader = loader; @@ -74,13 +81,19 @@ public ConfigBuilder withConverters(Converter... converters) { @Override public Config build() { List configSources = new ArrayList<>(); + if (forClassLoader == null) { + forClassLoader = Thread.currentThread().getContextClassLoader(); + if (forClassLoader == null) { + forClassLoader = DefaultConfigProvider.class.getClassLoader(); + } + } if (!ignoreDefaultSources) { configSources.addAll(getBuiltInConfigSources(forClassLoader)); } configSources.addAll(sources); - if (!ignoreDefaultSources) { + if (!ignoreDiscoveredSources) { // load all ConfigSource services ServiceLoader configSourceLoader = ServiceLoader.load(ConfigSource.class, forClassLoader); configSourceLoader.forEach(configSource -> configSources.add(configSource)); diff --git a/impl/src/main/java/org/apache/geronimo/config/DefaultConfigProvider.java b/impl/src/main/java/org/apache/geronimo/config/DefaultConfigProvider.java index d8a655f..d70b9d2 100644 --- a/impl/src/main/java/org/apache/geronimo/config/DefaultConfigProvider.java +++ b/impl/src/main/java/org/apache/geronimo/config/DefaultConfigProvider.java @@ -43,13 +43,10 @@ public class DefaultConfigProvider extends ConfigProviderResolver { @Override public Config getConfig() { - ClassLoader cl = Thread.currentThread().getContextClassLoader(); - if (cl == null) { - cl = DefaultConfigProvider.class.getClassLoader(); - } - return getConfig(cl); + return getConfig(null); } + @Override public Config getConfig(ClassLoader forClassLoader) { @@ -58,7 +55,7 @@ public Config getConfig(ClassLoader forClassLoader) { synchronized (DefaultConfigProvider.class) { config = existingConfig(forClassLoader); if (config == null) { - config = getBuilder().forClassLoader(forClassLoader).addDefaultSources().build(); + config = getBuilder().forClassLoader(forClassLoader).addDefaultSources().addDiscoveredSources().build(); registerConfig(config, forClassLoader); } } @@ -87,6 +84,15 @@ public ConfigBuilder getBuilder() { @Override public void releaseConfig(Config config) { + if (config == null) { + // get the config from the current TCCL + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + if (classLoader == null) { + classLoader = DefaultConfigProvider.class.getClassLoader(); + } + config = existingConfig(classLoader); + } + if (config != null) { synchronized (DefaultConfigProvider.class) { Iterator>> it = configs.entrySet().iterator(); diff --git a/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java b/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java index f22e8b5..94b1b39 100644 --- a/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java +++ b/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java @@ -35,6 +35,7 @@ import javax.enterprise.inject.spi.ProcessInjectionPoint; import javax.inject.Provider; +import org.apache.geronimo.config.DefaultConfigProvider; import org.eclipse.microprofile.config.Config; import org.eclipse.microprofile.config.ConfigProvider; import org.eclipse.microprofile.config.inject.ConfigProperty; @@ -44,6 +45,8 @@ */ public class ConfigExtension implements Extension { + private Config config; + private Set injectionPoints = new HashSet<>(); public void collectConfigProducer(@Observes ProcessInjectionPoint pip) { @@ -69,7 +72,7 @@ public void registerConfigProducer(@Observes AfterBeanDiscovery abd, BeanManager public void validate(@Observes AfterDeploymentValidation add) { List deploymentProblems = new ArrayList<>(); - Config config = ConfigProvider.getConfig(); + config = ConfigProvider.getConfig(); for (InjectionPoint injectionPoint : injectionPoints) { Type type = injectionPoint.getType(); @@ -92,7 +95,7 @@ public void validate(@Observes AfterDeploymentValidation add) { } public void shutdown(@Observes BeforeShutdown bsd) { - //X TODO shutdown config + DefaultConfigProvider.instance().releaseConfig(config); } From 0dda0802f955aed1b44e7f5115a485dbff886c27 Mon Sep 17 00:00:00 2001 From: Mark Struberg Date: Sat, 15 Apr 2017 21:03:26 +0200 Subject: [PATCH 28/29] update Arquillian and fix copyright --- NOTICE | 2 +- impl/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/NOTICE b/NOTICE index 4571a01..231dcfe 100644 --- a/NOTICE +++ b/NOTICE @@ -1,4 +1,4 @@ -Copyright 2009-2017 original author and authors +Copyright 2009-2017 Mark Struberg This product includes software developed at The Apache Software Foundation (http://www.apache.org/). \ No newline at end of file diff --git a/impl/pom.xml b/impl/pom.xml index c4b5177..f67ec8a 100644 --- a/impl/pom.xml +++ b/impl/pom.xml @@ -31,7 +31,7 @@ config-impl - 1.1.7.Final + 1.1.13.Final From 5a7500572f15f06c65966c53ced8bbae46177edd Mon Sep 17 00:00:00 2001 From: Mark Struberg Date: Sat, 22 Apr 2017 13:59:15 +0200 Subject: [PATCH 29/29] update README to point to the proper Apache Geronimo Config location --- README.adoc | 44 +++++++++++++------------------------------- 1 file changed, 13 insertions(+), 31 deletions(-) diff --git a/README.adoc b/README.adoc index 3a083aa..e346ca3 100644 --- a/README.adoc +++ b/README.adoc @@ -19,46 +19,28 @@ ## Status -Microprofile proposal! +The content of this repository is OUTDATED! -== Rational +Please go to the Apache Geronimo Config project for further information. -Many project artifacts (e.g. WAR, EAR) should only be created once and then get installed at different customers, stages, etc -They need to target those different execution environments without necessity of any repackaging. -In other words: depending on the situation they need different configuration. - -This is easily achievable by having a set of default configuration values inside the project artifact. -But be able to overwrite those default values from external. +$> svn co https://svn.apache.org/repos/asf/geronimo/components/config/trunk == History -This very configuration approach has it's roots in the Apache OpenWebBeans internal SPI configuration. -In 2010 it got moved over to the Apache MyFaces CODI project and enhanced to also fit the need of customer projects by Gerhard Petracek and Mark Struberg. -In 2011 we further enhanced it while moving CODI to the Apache DeltaSpike project. -Romain Manni-Bucau (Apache/Tomitribe), Ron Smeral (JBoss) and Anatole Tresch also gave appreciated input in the last years. - -== How it works - -A 'Configuration' consists of the information collected from the registered `javax.config.spi.ConfigSource` s. -These `ConfigSource`s get sorted according to their _ordinal_. -That way it is possible to overwrite configuration with lower importance from outside. - -By default there are 3 default ConfigSources: +This repository contains the original MicroProfile Config proposal and a Config JSR proposal based on the concepts Gerhard and I created in Apache OpenWebBeans, CODI and DeltaSpike. +See the separate branches for more info. -* `System.getenv()` (ordinal=400) -* `System.getProperties()` (ordinal=300) -* all `META-INF/microprofile-config.properties` files on the ClassPath. (ordinal=100, separately configurable via a config_ordinal property inside each file) +== The Config API -That means that I can put my default configuration in a `META-INF/microprofile-config.properties` anywhere on the classpath. -And I can later simply e.g set a system property to change this default configuration. +The API later got moved to the MicroProfile repository which itself later moved under the Eclipse umbrella. +It now can be found at -== Custom ConfigSources +https://github.com/eclipse/microprofile-config/ -It is possible to write and register custom `ConfigSource` s. -An example would be a ConfigSource which gets the configured values from a shared database table in a cluster. -== Building +== The Config IMPL -`$> mvn clean install` +The implementation of MicroProfile Config can be found at the Apache Geronimo Project. -After that the specification PDF can be found in `spec/target/generated-docs/microprofile-config-spec.pdf` \ No newline at end of file +$> svn co https://svn.apache.org/repos/asf/geronimo/components/config/trunk +