Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 8C627200B90 for ; Sun, 25 Sep 2016 23:24:05 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 8AE95160ACE; Sun, 25 Sep 2016 21:24:05 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 7045A160ABE for ; Sun, 25 Sep 2016 23:24:03 +0200 (CEST) Received: (qmail 38883 invoked by uid 500); 25 Sep 2016 21:24:02 -0000 Mailing-List: contact commits-help@tamaya.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@tamaya.incubator.apache.org Delivered-To: mailing list commits@tamaya.incubator.apache.org Received: (qmail 38874 invoked by uid 99); 25 Sep 2016 21:24:02 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd2-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 25 Sep 2016 21:24:02 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd2-us-west.apache.org (ASF Mail Server at spamd2-us-west.apache.org) with ESMTP id D46151A0051 for ; Sun, 25 Sep 2016 21:24:01 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd2-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: -4.646 X-Spam-Level: X-Spam-Status: No, score=-4.646 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, KAM_LAZY_DOMAIN_SECURITY=1, RCVD_IN_DNSWL_HI=-5, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RP_MATCHES_RCVD=-1.426] autolearn=disabled Received: from mx1-lw-eu.apache.org ([10.40.0.8]) by localhost (spamd2-us-west.apache.org [10.40.0.9]) (amavisd-new, port 10024) with ESMTP id I5oHNqNWqh2R for ; Sun, 25 Sep 2016 21:23:55 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx1-lw-eu.apache.org (ASF Mail Server at mx1-lw-eu.apache.org) with SMTP id DE041611EA for ; Sun, 25 Sep 2016 21:23:51 +0000 (UTC) Received: (qmail 36627 invoked by uid 99); 25 Sep 2016 21:23:50 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 25 Sep 2016 21:23:50 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 43C9CE0252; Sun, 25 Sep 2016 21:23:50 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: plexus@apache.org To: commits@tamaya.incubator.apache.org Date: Sun, 25 Sep 2016 21:24:37 -0000 Message-Id: <08f2efc728fd48e883cb695fd7344258@git.apache.org> In-Reply-To: <52a24ee3fa43434897c8fbb3b85ab5f9@git.apache.org> References: <52a24ee3fa43434897c8fbb3b85ab5f9@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [49/50] [abbrv] incubator-tamaya-sandbox git commit: Moved the builder to the directory builder archived-at: Sun, 25 Sep 2016 21:24:05 -0000 Moved the builder to the directory builder Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/commit/f45a5bb5 Tree: http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/tree/f45a5bb5 Diff: http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/diff/f45a5bb5 Branch: refs/heads/master Commit: f45a5bb5bc1f2bb439980fda4f0da7fae70c19d4 Parents: 09ab45b Author: Oliver B. Fischer Authored: Sun Sep 25 23:20:22 2016 +0200 Committer: Oliver B. Fischer Committed: Sun Sep 25 23:20:22 2016 +0200 ---------------------------------------------------------------------- builder/pom.xml | 104 +++ .../tamaya/builder/ConfigurationBuilder.java | 605 +++++++++++++ .../ProgrammaticConfigurationContext.java | 388 ++++++++ .../tamaya/builder/PropertySourceBuilder.java | 118 +++ .../tamaya/builder/SimplePropertySource.java | 86 ++ .../org/apache/tamaya/builder/package-info.java | 28 + .../builder/ConfigurationBuilderTest.java | 907 +++++++++++++++++++ .../builder/TestANonSPIPropertyFilter.java | 35 + .../builder/TestBNonSPIPropertyFilter.java | 35 + .../tamaya/builder/TestPropertyFilter.java | 35 + .../tamaya/builder/TestPropertySource.java | 59 ++ .../builder/TestPropertySourceProvider.java | 91 ++ .../builder/TestPropertySourceProviderB.java | 91 ++ .../builder/util/mockito/NotMockedAnswer.java | 57 ++ .../tamaya/builder/util/types/CustomTypeA.java | 34 + .../tamaya/builder/util/types/CustomTypeB.java | 39 + .../tamaya/builder/util/types/CustomTypeC.java | 36 + .../types/CustomTypeCPropertyConverter.java | 29 + .../org.apache.tamaya.spi.PropertyConverter | 19 + .../org.apache.tamaya.spi.PropertyFilter | 19 + .../org.apache.tamaya.spi.PropertySource | 19 + ...org.apache.tamaya.spi.PropertySourceProvider | 19 + .../test/resources/configfiles/json/first.json | 4 + .../test/resources/configfiles/json/second.json | 4 + .../test/resources/configfiles/json/simple.json | 4 + .../test/resources/configfiles/json/third.json | 4 + .../test/resources/configfiles/other/simple.oml | 19 + pom.xml | 104 --- .../tamaya/builder/ConfigurationBuilder.java | 605 ------------- .../ProgrammaticConfigurationContext.java | 388 -------- .../tamaya/builder/PropertySourceBuilder.java | 118 --- .../tamaya/builder/SimplePropertySource.java | 86 -- .../org/apache/tamaya/builder/package-info.java | 28 - .../builder/ConfigurationBuilderTest.java | 907 ------------------- .../builder/TestANonSPIPropertyFilter.java | 35 - .../builder/TestBNonSPIPropertyFilter.java | 35 - .../tamaya/builder/TestPropertyFilter.java | 35 - .../tamaya/builder/TestPropertySource.java | 59 -- .../builder/TestPropertySourceProvider.java | 91 -- .../builder/TestPropertySourceProviderB.java | 91 -- .../builder/util/mockito/NotMockedAnswer.java | 57 -- .../tamaya/builder/util/types/CustomTypeA.java | 34 - .../tamaya/builder/util/types/CustomTypeB.java | 39 - .../tamaya/builder/util/types/CustomTypeC.java | 36 - .../types/CustomTypeCPropertyConverter.java | 29 - .../org.apache.tamaya.spi.PropertyConverter | 19 - .../org.apache.tamaya.spi.PropertyFilter | 19 - .../org.apache.tamaya.spi.PropertySource | 19 - ...org.apache.tamaya.spi.PropertySourceProvider | 19 - src/test/resources/configfiles/json/first.json | 4 - src/test/resources/configfiles/json/second.json | 4 - src/test/resources/configfiles/json/simple.json | 4 - src/test/resources/configfiles/json/third.json | 4 - src/test/resources/configfiles/other/simple.oml | 19 - 54 files changed, 2888 insertions(+), 2888 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/f45a5bb5/builder/pom.xml ---------------------------------------------------------------------- diff --git a/builder/pom.xml b/builder/pom.xml new file mode 100644 index 0000000..96f6244 --- /dev/null +++ b/builder/pom.xml @@ -0,0 +1,104 @@ + + + + 4.0.0 + + + org.apache.tamaya.ext + tamaya-extensions + 0.3-incubating-SNAPSHOT + + + tamaya-builder + Apache Tamaya Modules - Builder + jar + + 2015 + + + + org.apache.tamaya + tamaya-api + ${project.version} + provided + + + + org.apache.tamaya.ext + tamaya-formats + ${project.version} + + + + org.apache.tamaya + tamaya-core + ${project.version} + test + + + + org.apache.tamaya.ext + tamaya-spisupport + ${project.version} + + + + org.apache.tamaya.ext + tamaya-json + ${project.version} + test + + + + org.hamcrest + java-hamcrest + + + + org.mockito + mockito-core + + + + junit + junit + + + + + + + + http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/f45a5bb5/builder/src/main/java/org/apache/tamaya/builder/ConfigurationBuilder.java ---------------------------------------------------------------------- diff --git a/builder/src/main/java/org/apache/tamaya/builder/ConfigurationBuilder.java b/builder/src/main/java/org/apache/tamaya/builder/ConfigurationBuilder.java new file mode 100644 index 0000000..afdc121 --- /dev/null +++ b/builder/src/main/java/org/apache/tamaya/builder/ConfigurationBuilder.java @@ -0,0 +1,605 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tamaya.builder; + +import org.apache.tamaya.ConfigException; +import org.apache.tamaya.Configuration; +import org.apache.tamaya.spi.PropertyConverter; +import org.apache.tamaya.TypeLiteral; +import org.apache.tamaya.format.ConfigurationData; +import org.apache.tamaya.format.ConfigurationFormats; +import org.apache.tamaya.format.FlattenedDefaultPropertySource; +import org.apache.tamaya.spi.ConfigurationContext; +import org.apache.tamaya.spi.PropertyFilter; +import org.apache.tamaya.spi.PropertySource; +import org.apache.tamaya.spi.PropertySourceProvider; +import org.apache.tamaya.spi.PropertyValueCombinationPolicy; +import org.apache.tamaya.spisupport.DefaultConfiguration; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Collection; +import java.util.Objects; + +import static java.lang.String.format; + +/** + *

Builder class used for building a configuration manually without relying + * only on the Service Provider Interface API.

+ * + *

Features of the builder

+ * + *
    + *
  1. Adding of property converters manually
  2. + *
  3. Adding of property sources directly
  4. + *
  5. Adding of property sources via URL
  6. + *
  7. Adding of property source providers directly
  8. + *
  9. Enabling and disabling of via SPI mechanism provided resources as converters, + * property sources, etc.
  10. + *
+ * + *

Example

+ * + *
{@code ConfigurationBuilder builder = new ConfigurationBuilder();
+ * builder.disableProvidedPropertySources()           // Do not load provided property
+ *        .disableProvidedPropertySourceProviders()   // sources and providers automatically
+ *        .addPropertySource("file:/etc/conf.properties"); // Load properties from conf.properties
+ *
+ * Configuration config = builder.build();
+ * }
+ * + *

Support for configuration formats

+ * + * The configuration builder allows you to put property resources + * via a URL, as shown in the code example above, without implementing + * a {@link org.apache.tamaya.spi.PropertySource PropertySource} or providing an + * instance of a {@link org.apache.tamaya.spi.PropertySource PropertySource}. + * If a property resource in + * a specific format can be added to configuration builder or not depends + * on the available implementations of + * {@link org.apache.tamaya.format.ConfigurationFormat} in the classpath. + * Which formats are available can be checked via + * {@link org.apache.tamaya.format.ConfigurationFormats#getFormats()}. + */ +public class ConfigurationBuilder { + /** Builder used to create new ConfigurationContext instances. */ + private final ProgrammaticConfigurationContext.Builder contextBuilder = new ProgrammaticConfigurationContext.Builder(); + + /** + * Flag if the config has already been built. + * Configuration can be built only once + */ + private boolean built; + + /** + * Flag if all existing property converter service providers + * should be loaded if the configuration is build. + */ + private boolean loadProvidedPropertyConverters = true; + + /** + * Flag if all existing property source service providers + * will be loaded if the configuration is build. + */ + private boolean loadProvidedPropertySources = false; + private boolean loadProvidedPropertySourceProviders = false; + + private boolean isLoadProvidedPropertyFilters = false; + + /** + * Creates a new builder instance. + */ + public ConfigurationBuilder() { + } + + /** + * Allows to set configuration context during unit tests. + */ + ConfigurationBuilder setConfigurationContext(ConfigurationContext configurationContext) { + //noinspection deprecation + contextBuilder.setConfigurationContext(configurationContext); + return this; + } + + /** + * Adds one resources with properties in an arbitrary format + * to the configuration to be build. + * + *

If a specific format is supported depends on the available + * {@link org.apache.tamaya.format.ConfigurationFormat} implementations.

+ * + *
{@code URL resource = new URL("file:/etc/service/config.json");
+     *
+     * builder.addPropertySources(resource);}
+     * 
+ * + * @param url resource with properties for the the configuration to be build. + * + * @return the builder instance currently used + * + * @see org.apache.tamaya.format.ConfigurationFormat + * @see org.apache.tamaya.format.ConfigurationFormats#getFormats() + */ + public ConfigurationBuilder addPropertySource(URL url) { + try { + ConfigurationData data = getConfigurationDataFromURL(url); + + FlattenedDefaultPropertySource propertySource = new FlattenedDefaultPropertySource(data); + addPropertySources(propertySource); + } catch (IOException e) { + throw new ConfigException("Failed to read " + url.toString(), e); + } + return this; + } + + protected ConfigurationData getConfigurationDataFromURL(URL url) throws IOException { + ConfigurationData data = ConfigurationFormats.readConfigurationData(url); + + if (null == data) { + String mesg = format("No configuration format found which is able " + + "to read properties from %s.", url.toString()); + + throw new ConfigException(mesg); + } + + return data; + } + + /** + * Adds one or more resources with properties in an arbitrary format + * to the configuration to be build. + * + *

If a specific format is supported depends on the available + * {@link org.apache.tamaya.format.ConfigurationFormat} implementations.

+ * + *
{@code URL first = new URL("file:/etc/service/config.json");
+     * URL second = new URL("file:/etc/defaults/values.properties");
+     *
+     * builder.addPropertySources(first, second);}
+     *
+ * + * @param urls list of resources with properties for the configuration to be + * build. + * + * @return the builder instance currently used + * + * @see org.apache.tamaya.format.ConfigurationFormat + * @see org.apache.tamaya.format.ConfigurationFormats#getFormats() + */ + public ConfigurationBuilder addPropertySources(URL... urls) { + for(URL url:urls){ + if(url!=null){ + addPropertySource(url); + } + } + return this; + } + + /** + * Adds one or more resources with properties in an arbitrary format + * to the configuration to be build. + * + *

If a specific format is supported depends on the available + * {@link org.apache.tamaya.format.ConfigurationFormat} implementations.

+ * + *
{@code URL first = new URL("file:/etc/service/config.json");
+     * URL second = new URL("file:/etc/defaults/values.properties");
+     *
+     * builder.addPropertySources(first, second);}
+     *
+ * + * @param urls list of resources with properties for the configuration to be + * build. + * + * @return the builder instance currently used + * + * @see org.apache.tamaya.format.ConfigurationFormat + * @see org.apache.tamaya.format.ConfigurationFormats#getFormats() + */ + public ConfigurationBuilder addPropertySources(Collection urls) { + for(URL url:urls) { + if (url != null) { + addPropertySource(url); + } + } + return this; + } + + + /** + * Adds one or more resources with properties in an arbitrary format + * to the configuration to be build. + * + *

If a specific format is supported depends on the available + * {@link org.apache.tamaya.format.ConfigurationFormat} implementations.

+ * + *
{@code builder.addPropertySources("file:/etc/service/config.json",
+     *                            "file:/etc/defaults/values.properties");}
+     *
+ * + * @param urls list of resources with properties for the configuration to be + * build. + * + * @return the builder instance currently used + * + * @see org.apache.tamaya.format.ConfigurationFormat + * @see org.apache.tamaya.format.ConfigurationFormats#getFormats() + */ + public ConfigurationBuilder addPropertySources(String... urls) { + for(String url:urls) { + if (url != null) { + try{ + addPropertySource(new URL(url)); + } catch(Exception e){ + throw new ConfigException("Invalid URL: " + url); + } + } + } + return this; + } + + /** + * Adds one or more property source instances to the configuration to be build. + * + *
{@code PropertySource first = new CustomPropertySource();
+     * PropertySource second = new YetAnotherPropertySource();
+     *
+     * builder.addPropertySources(first, second)};
+     *
+ * + * @param sources list of property source instances with properties for the + * configuration to be build. + * + * @return the builder instance currently used + * + * @see org.apache.tamaya.spi.PropertySource + */ + public ConfigurationBuilder addPropertySources(PropertySource... sources){ + checkBuilderState(); + + contextBuilder.addPropertySources(Objects.requireNonNull(sources)); + return this; + } + + private void checkBuilderState() { + if (built) { + throw new IllegalStateException("Configuration has already been build."); + } + } + + /** + * Adds one or more property source provider instances to the configuration to be build. + * + *
{@code PropertySourceProvider jc = new JavaConfigurationProvider();
+     *
+     * builder.addPropertySources(jc)};
+     * 
+ * + * @param providers list of property source provider instances each providing a set + * of property source instances for the configuration to be build. + * + * @return the builder instance currently used + * + * @see org.apache.tamaya.spi.PropertySourceProvider + */ + public ConfigurationBuilder addPropertySourceProviders(PropertySourceProvider... providers){ + contextBuilder.addPropertySourceProviders(providers); + return this; + } + + /** + * Adds one or more property filter instances to the configuration to be build. + * + *
{@code PropertyFilter quoteReplacingFilter = new QuoteFilter();
+     * PropertyFilter commaRemovingFilter = new CommaFilter();
+     *
+     * builder.addPropertyFilters(commaRemovingFilter, quoteReplacingFilter)};
+     * 
+ * + * @param filters list of property filter instances which should be applied + * to the properties of the configuration to be build. + * + * @return the builder instance currently used + * + * @see org.apache.tamaya.spi.PropertyFilter + * @see #disableProvidedPropertyFilters() + * @see #enabledProvidedPropertyFilters() + */ + public ConfigurationBuilder addPropertyFilters(PropertyFilter... filters){ + Objects.requireNonNull(filters); + + contextBuilder.addPropertyFilters(filters); + return this; + } + + + /** + * @param propertyValueCombinationPolicy combination policy to use for this builder. + * @return the builder instance currently in use. + */ + public ConfigurationBuilder setPropertyValueCombinationPolicy(PropertyValueCombinationPolicy propertyValueCombinationPolicy){ + contextBuilder.setPropertyValueCombinationPolicy(propertyValueCombinationPolicy); + return this; + } + + /** + * Adds a property converter for the a given type to the configuration to + * be build. + * + *
{@code PropertyConverter converter = value -> new MyType(value, 42);
+     *
+     * builder.addPropertyConverter(MyType.class, converter}
+     * 
+ * + * @param the type of the configuration + * @param type the required target type the converter should be applied to + * @param converter the converter to be used to convert the string property + * to the given target type. + * + * @return the builder instance currently used + * + * @see org.apache.tamaya.spi.PropertyConverter + * @see #enableProvidedPropertyConverters() + * @see #disableProvidedPropertyConverters() + */ + public ConfigurationBuilder addPropertyConverter(Class type, PropertyConverter converter) { + Objects.requireNonNull(type); + Objects.requireNonNull(converter); + return addPropertyConverter(TypeLiteral.of(type), (PropertyConverter)converter); + } + + /** + * Adds a propertyConverter of a given type. + * + * @param the type of the configuration + * @param type type literal of this converter. + * @param propertyConverter property converter. + * @return the builder instance currently used + */ + public ConfigurationBuilder addPropertyConverter(TypeLiteral type, PropertyConverter propertyConverter){ + Objects.requireNonNull(type); + Objects.requireNonNull(propertyConverter); + contextBuilder.addPropertyConverter(type, propertyConverter); + return this; + } + + /** + * Checks if the automatic loading of all {@link org.apache.tamaya.spi.PropertyConverter + * PropertyConverter} service providers is enabled or disabled. + * + * @return {@code true} if the automatic loading is enabled, + * otherwise {@code false}. + * + * @see #enableProvidedPropertyConverters() + * @see #disableProvidedPropertyConverters() + * @see #addPropertyConverter(Class, org.apache.tamaya.spi.PropertyConverter) + * @see #addPropertyConverter(org.apache.tamaya.TypeLiteral, org.apache.tamaya.spi.PropertyConverter) + */ + public boolean isPropertyConverterLoadingEnabled() { + return loadProvidedPropertyConverters; + } + + /** + * Enables the loading of all {@link org.apache.tamaya.spi.PropertyConverter} + * service providers. + * + * @return the builder instance currently used + * + * @see org.apache.tamaya.spi.PropertyConverter + * @see #disableProvidedPropertyConverters() + * @see #enableProvidedPropertyConverters() + */ + public ConfigurationBuilder enableProvidedPropertyConverters() { + checkBuilderState(); + + loadProvidedPropertyConverters = true; + + return this; + } + + /** + * Disables the automatic loading of all {@link org.apache.tamaya.spi.PropertyConverter} + * service providers. + * + * @return the builder instance currently used + * + * @see org.apache.tamaya.spi.PropertyConverter + * @see #enableProvidedPropertyConverters() + * @see #addPropertyConverter(Class, org.apache.tamaya.spi.PropertyConverter) + */ + public ConfigurationBuilder disableProvidedPropertyConverters() { + checkBuilderState(); + + loadProvidedPropertyConverters = false; + + return this; + } + + + /** + * Enables the automatic loading of all {@link org.apache.tamaya.spi.PropertySource} + * service providers. + * + * @return the builder instance currently used + * + * @see org.apache.tamaya.spi.PropertySource + * @see #disableProvidedPropertySources() + */ + public ConfigurationBuilder enableProvidedPropertySources() { + checkBuilderState(); + + loadProvidedPropertySources = true; + + return this; + } + + /** + * Checks if the automatic loading of all {@link org.apache.tamaya.spi.PropertySource + * PropertySource} service providers is enabled or disabled. + * + * @return {@code true} if the automatic loading is enabled, + * otherwise {@code false}. + */ + public boolean isPropertySourcesLoadingEnabled() { + return loadProvidedPropertySources; + } + + + /** + * Checks if the automatic loading of all {@link org.apache.tamaya.spi.PropertyFilter + * PropertyFilter} service providers is enabled or disabled. + * + * @return {@code true} if the automatic loading is enabled, + * otherwise {@code false}. + */ + public boolean isPropertyFilterLoadingEnabled() { + return isLoadProvidedPropertyFilters; + } + + /** + * Enables the automatic loading of all {@link org.apache.tamaya.spi.PropertyFilter} + * service providers. + * + * @return the builder instance currently used + * + * @see org.apache.tamaya.spi.PropertyFilter + * @see #disableProvidedPropertyFilters() + * @see #addPropertyFilters(org.apache.tamaya.spi.PropertyFilter...) + */ + public ConfigurationBuilder enabledProvidedPropertyFilters() { + checkBuilderState(); + + isLoadProvidedPropertyFilters = true; + + return this; + } + + /** + * Disables the automatic loading of all {@link org.apache.tamaya.spi.PropertyFilter} + * service providers. + * + * @see org.apache.tamaya.spi.PropertyFilter + * @see #enabledProvidedPropertyFilters() + * @see #addPropertyFilters(org.apache.tamaya.spi.PropertyFilter...) + * + * @return the builder instance currently used + */ + public ConfigurationBuilder disableProvidedPropertyFilters() { + checkBuilderState(); + + isLoadProvidedPropertyFilters = false; + + return this; + } + + /** + * Disables the automatic loading of all {@link org.apache.tamaya.spi.PropertySource} + * service providers. + * + * @return the builder instance currently used + * + * @see org.apache.tamaya.spi.PropertySource + * @see #enableProvidedPropertySources() + */ + public ConfigurationBuilder disableProvidedPropertySources() { + checkBuilderState(); + + loadProvidedPropertySources = false; + + return this; + } + + /** + * Enables the automatic loading of {@link org.apache.tamaya.spi.PropertySourceProvider + * property source providers} provided via the SPI API. + * + * @return the builder instance currently used + * + * @see org.apache.tamaya.spi.PropertySourceProvider + */ + public ConfigurationBuilder enableProvidedPropertySourceProviders() { + checkBuilderState(); + + loadProvidedPropertySourceProviders = true; + + return this; + } + + /** + * Disables the automatic loading of {@link org.apache.tamaya.spi.PropertySourceProvider + * property source providers} provided via the SPI API. + * + * @return the builder instance currently used + */ + public ConfigurationBuilder disableProvidedPropertySourceProviders() { + checkBuilderState(); + + loadProvidedPropertySourceProviders = false; + + return this; + } + + /** + * Checks if the automatic loading of {@link org.apache.tamaya.spi.PropertySourceProvider + * PropertySourceProviders} is enabled or disabled. + * + * @return {@code true} if the automatic loading is enabled, + * otherwise {@code false}. + */ + public boolean isPropertySourceProvidersLoadingEnabled() { + return loadProvidedPropertySourceProviders; + } + + //X TODO think on a functionality/API for using the default PropertyConverters and use the configured ones here + //X TODO as overrides used first. + + + /** + * Builds a new configuration based on the configuration of this builder instance. + * + * @return a new {@link org.apache.tamaya.Configuration configuration instance}, + * never {@code null}. + */ + public Configuration build() { + checkBuilderState(); + + built = true; + + contextBuilder.loadProvidedPropertyConverters(isPropertyConverterLoadingEnabled()); + contextBuilder.loadProvidedPropertySources(isPropertySourcesLoadingEnabled()); + contextBuilder.loadProvidedPropertySourceProviders(isPropertySourceProvidersLoadingEnabled()); + contextBuilder.loadProvidedPropertyFilters(isLoadProvidedPropertyFilters); + + return new DefaultConfiguration(contextBuilder.build()); + } + + /** + * Mapper to map a URL given as string to an URL instance. + */ + private static class StringToURLMapper { + public URL apply(String u) { + try { + return new URL(u); + } catch (MalformedURLException e) { + throw new ConfigException(u + " is not a valid URL", e); + } + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/f45a5bb5/builder/src/main/java/org/apache/tamaya/builder/ProgrammaticConfigurationContext.java ---------------------------------------------------------------------- diff --git a/builder/src/main/java/org/apache/tamaya/builder/ProgrammaticConfigurationContext.java b/builder/src/main/java/org/apache/tamaya/builder/ProgrammaticConfigurationContext.java new file mode 100644 index 0000000..68e770d --- /dev/null +++ b/builder/src/main/java/org/apache/tamaya/builder/ProgrammaticConfigurationContext.java @@ -0,0 +1,388 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tamaya.builder; + + +import org.apache.tamaya.spi.PropertyConverter; +import org.apache.tamaya.TypeLiteral; +import org.apache.tamaya.spi.ConfigurationContext; +import org.apache.tamaya.spi.ConfigurationContextBuilder; +import org.apache.tamaya.spi.PropertyFilter; +import org.apache.tamaya.spi.PropertySource; +import org.apache.tamaya.spi.PropertySourceProvider; +import org.apache.tamaya.spi.PropertyValueCombinationPolicy; +import org.apache.tamaya.spi.ServiceContextManager; +import org.apache.tamaya.spisupport.PriorityServiceComparator; +import org.apache.tamaya.spisupport.PropertyConverterManager; +import org.apache.tamaya.spisupport.PropertySourceComparator; + +import javax.annotation.Priority; +import java.util.*; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.logging.Logger; + +/** + * Implementation of the {@link org.apache.tamaya.spi.ConfigurationContext} + * used by the {@link org.apache.tamaya.builder.ConfigurationBuilder} + * internally. + */ +class ProgrammaticConfigurationContext implements ConfigurationContext { + + private static final Comparator PS_COMPARATOR = new PropertySourceComparator(); + private static final Comparator COMP_COMPARATOR = new PriorityServiceComparator(); + /** + * The logger used. + */ + private final static Logger LOG = Logger.getLogger(ProgrammaticConfigurationContext.class.getName()); + /** + * Cubcomponent handling {@link org.apache.tamaya.spi.PropertyConverter} instances. + */ + private PropertyConverterManager propertyConverterManager = new PropertyConverterManager(); + + /** + * The current unmodifiable list of loaded {@link org.apache.tamaya.spi.PropertySource} instances. + */ + private List immutablePropertySources = new ArrayList<>(); + + /** + * The current unmodifiable list of loaded {@link org.apache.tamaya.spi.PropertyFilter} instances. + */ + private List immutablePropertyFilters = new ArrayList<>(); + + /** + * The overriding policy used when combining PropertySources registered to evalute the final configuration + * values. + */ + private PropertyValueCombinationPolicy propertyValueCombinationPolicy; + + /** + * Lock for internal synchronization. + */ + private final ReadWriteLock propertySourceLock = new ReentrantReadWriteLock(); + + + /** + * The first time the Configuration system gets invoked we do initialize + * all our {@link org.apache.tamaya.spi.PropertySource}s and + * {@link org.apache.tamaya.spi.PropertyFilter}s which are known at startup. + */ + @SuppressWarnings("unchecked") + public ProgrammaticConfigurationContext(Builder builder) { + propertyConverterManager = new PropertyConverterManager(builder.loadProvidedPropertyConverters); + + List sources = getAllPropertySources(builder); + Collections.sort(sources, PS_COMPARATOR); + immutablePropertySources = Collections.unmodifiableList(sources); + + + List filters = getPropertyFilters(builder); + Collections.sort(filters, COMP_COMPARATOR); + immutablePropertyFilters = Collections.unmodifiableList(filters); + + + propertyValueCombinationPolicy = builder.propertyValueCombinationPolicy; + for(Map.Entry, List>> en: builder.propertyConverters.entrySet()){ + if(en!=null){ + for(PropertyConverter pv:en.getValue()) { + propertyConverterManager.register(en.getKey(), pv); + } + } + } + + LOG.info("Using " + immutablePropertySources.size() + " property sources: " + immutablePropertySources); + LOG.info("Using " + immutablePropertyFilters.size() + " property filters: " + immutablePropertyFilters); + LOG.info("Using PropertyValueCombinationPolicy: " + propertyValueCombinationPolicy); + } + + private List getPropertyFilters(Builder builder) { + List provided = new ArrayList<>(); + if(builder.loadProvidedPropertyFilters) { + provided.addAll(ServiceContextManager.getServiceContext().getServices(PropertyFilter.class)); + } + for(PropertyFilter pf:builder.propertyFilters) { + if (pf != null) { + provided.add(pf); + } + } + return provided; + } + + private List getAllPropertySources(Builder builder) { + List provided = new ArrayList<>(); + if(builder.loadProvidedPropertySources) { + provided.addAll(ServiceContextManager.getServiceContext().getServices(PropertySource.class)); + } + for(PropertySource ps:builder.propertySources){ + if(ps!=null){ + provided.add(ps); + } + } + if (builder.loadProvidedPropertySourceProviders) { + List providers = ServiceContextManager.getServiceContext() + .getServices(PropertySourceProvider.class); + for (PropertySourceProvider provider : providers) { + for(PropertySource ps:provider.getPropertySources()) { + if(ps!=null) { + provided.addAll(provider.getPropertySources()); + } + } + } + } + return provided; + } + + public void addPropertySources(PropertySource... propertySourcesToAdd) { + Lock writeLock = propertySourceLock.writeLock(); + try { + writeLock.lock(); + List provided = new ArrayList<>(); + for(PropertySource ps:propertySourcesToAdd){ + if(ps!=null){ + provided.add(ps); + } + } + this.immutablePropertySources = Collections.unmodifiableList(provided); + } finally { + writeLock.unlock(); + } + } + + /** + * Order property source reversely, the most important come first. + * + * @param source1 the first PropertySource + * @param source2 the second PropertySource + * @return the comparison result. + */ + private int comparePropertySources(PropertySource source1, PropertySource source2) { + + //X TODO this method duplicates org.apache.tamaya.core.internal.DefaultConfigurationContext.PropertySourceComparator.comparePropertySources() + //X maybe we should extract the Comperator in an own class for real code-reuse (copy paste == bad code reuse) + + if (source1.getOrdinal() < source2.getOrdinal()) { + return -1; + } else if (source1.getOrdinal() > source2.getOrdinal()) { + return 1; + } else { + return source1.getClass().getName().compareTo(source2.getClass().getName()); + } + } + + /** + * Compare 2 filters for ordering the filter chain. + * + * @param filter1 the first filter + * @param filter2 the second filter + * @return the comparison result + */ + private int comparePropertyFilters(PropertyFilter filter1, PropertyFilter filter2) { + + //X TODO this method duplicates org.apache.tamaya.core.internal.DefaultConfigurationContext.PropertySourceComparator.comparePropertyFilters() + //X maybe we should extract the Comperator in an own class for real code-reuse (copy paste == bad code reuse) + + Priority prio1 = filter1.getClass().getAnnotation(Priority.class); + Priority prio2 = filter2.getClass().getAnnotation(Priority.class); + int ord1 = prio1 != null ? prio1.value() : 0; + int ord2 = prio2 != null ? prio2.value() : 0; + + if (ord1 < ord2) { + return -1; + } else if (ord1 > ord2) { + return 1; + } else { + return filter1.getClass().getName().compareTo(filter2.getClass().getName()); + } + } + + @Override + public List getPropertySources() { + return immutablePropertySources; + } + + public void addPropertyConverter(TypeLiteral typeToConvert, PropertyConverter propertyConverter) { + propertyConverterManager.register(typeToConvert, propertyConverter); + LOG.info("Added PropertyConverter: " + propertyConverter.getClass().getName()); + } + + @Override + public Map, List>> getPropertyConverters() { + return propertyConverterManager.getPropertyConverters(); + } + + @Override + public List> getPropertyConverters(TypeLiteral targetType) { + return propertyConverterManager.getPropertyConverters(targetType); + } + + @Override + public List getPropertyFilters() { + return immutablePropertyFilters; + } + + @Override + public PropertyValueCombinationPolicy getPropertyValueCombinationPolicy() { + return propertyValueCombinationPolicy; + } + + + @Override + public ConfigurationContextBuilder toBuilder() { + // @todo Check if it could be useful to support this method, Oliver B. Fischer + throw new RuntimeException("This method is currently not supported."); + } + + /** + * The Builder for {@link ProgrammaticConfigurationContext} + */ + public final static class Builder { + /** + * The current unmodifiable list of loaded {@link org.apache.tamaya.spi.PropertySource} instances. + */ + private final List propertySources = new ArrayList<>(); + + /** + * The current unmodifiable list of loaded {@link org.apache.tamaya.spi.PropertyFilter} instances. + */ + private final List propertyFilters = new ArrayList<>(); + + private final Map, List>> propertyConverters = new HashMap<>(); + + /** + * The overriding policy used when combining PropertySources registered to evalute the final configuration + * values. + */ + private PropertyValueCombinationPolicy propertyValueCombinationPolicy = + PropertyValueCombinationPolicy.DEFAULT_OVERRIDING_COLLECTOR; + + private boolean loadProvidedPropertyConverters; + private boolean loadProvidedPropertySources; + private boolean loadProvidedPropertySourceProviders; + private boolean loadProvidedPropertyFilters; + + public Builder setPropertyValueCombinationPolicy(PropertyValueCombinationPolicy policy) { + this.propertyValueCombinationPolicy = Objects.requireNonNull(policy); + return this; + } + + public Builder addPropertySources(PropertySource... propertySources) { + for (PropertySource ps : propertySources) { + if (ps != null) { + this.propertySources.add(ps); + } + } + return this; + } + + public Builder addPropertySources(Collection propertySources) { + for (PropertySource ps : propertySources) { + if (ps != null) { + this.propertySources.add(ps); + } + } + return this; + } + + public Builder addPropertySourceProviders(PropertySourceProvider... propertySourceProviders) { + for (PropertySourceProvider ps : propertySourceProviders) { + if (ps != null) { + this.propertySources.addAll(ps.getPropertySources()); + } + } + return this; + } + + public Builder addPropertySourceProviders(Collection propertySourceProviders) { + for (PropertySourceProvider ps : propertySourceProviders) { + if (ps != null) { + this.propertySources.addAll(ps.getPropertySources()); + } + } + return this; + } + + public Builder addPropertyFilters(PropertyFilter... propertyFIlter) { + for (PropertyFilter pf : propertyFIlter) { + if (pf != null) { + this.propertyFilters.add(pf); + } + } + return this; + } + + public Builder addPropertyFilters(Collection propertyFIlter) { + for (PropertyFilter pf : propertyFIlter) { + if (pf != null) { + this.propertyFilters.add(pf); + } + } + return this; + } + + /** + * Should be never used. + */ + @Deprecated + public Builder setConfigurationContext(ConfigurationContext configurationContext) { + this.addPropertySources(configurationContext.getPropertySources()); + this.addPropertyFilters(configurationContext.getPropertyFilters()); + this.propertyValueCombinationPolicy = Objects.requireNonNull( + configurationContext.getPropertyValueCombinationPolicy()); + return this; + } + + //X TODO think on a functonality/API for using the default PropertyConverters and use the configured ones here + //X TODO as overrides used first. + + public Builder addPropertyConverter(TypeLiteral type, PropertyConverter propertyConverter) { + if(!propertyConverters.containsKey(type)){ + List> convList = new ArrayList<>(); + convList.add(propertyConverter); + propertyConverters.put(type, convList); + } + return this; + } + + public ConfigurationContext build() { + return new ProgrammaticConfigurationContext(this); + } + + + public void loadProvidedPropertyConverters(boolean state) { + loadProvidedPropertyConverters = state; + } + + public void loadProvidedPropertySources(boolean state) { + loadProvidedPropertySources = state; + } + + public void loadProvidedPropertySourceProviders(boolean state) { + loadProvidedPropertySourceProviders = state; + } + + public void loadProvidedPropertyFilters(boolean state) { + loadProvidedPropertyFilters = state; + } + + } + + + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/f45a5bb5/builder/src/main/java/org/apache/tamaya/builder/PropertySourceBuilder.java ---------------------------------------------------------------------- diff --git a/builder/src/main/java/org/apache/tamaya/builder/PropertySourceBuilder.java b/builder/src/main/java/org/apache/tamaya/builder/PropertySourceBuilder.java new file mode 100644 index 0000000..481a80c --- /dev/null +++ b/builder/src/main/java/org/apache/tamaya/builder/PropertySourceBuilder.java @@ -0,0 +1,118 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tamaya.builder; + +import org.apache.tamaya.spi.PropertySource; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * Simple builder for building a {@link org.apache.tamaya.spi.PropertySource}. + */ +public final class PropertySourceBuilder { + /** The ordinal to be used. */ + private int ordinal; + /** The name to be used. */ + private final String name; + /** The properties. */ + private final Map properties = new HashMap<>(); + + /** private constructor. */ + private PropertySourceBuilder(String name){ + this.name = Objects.requireNonNull(name); + } + + /** + * Gets a new instance of a builder. + * @param name The name of the property source, not null. + * @return a new instance. + */ + public static PropertySourceBuilder of(String name){ + return new PropertySourceBuilder(name); + } + + /** + * Gets a new instance of a builder. + * @param name The name of the property source, not null. + * @return a new instance. + */ + public static PropertySourceBuilder from(String name){ + return new PropertySourceBuilder(name); + } + + /** + * Sets a new property key/value. + * @param key the property key, not null. + * @param value the property value, not null. + * @return the bulder for chaining. + */ + public PropertySourceBuilder put(String key, String value){ + this.properties.put(key, value); + return this; + } + + /** + * Put all the given key, values. + * @param values the new key/values, not null. + * @return the bulder for chaining. + */ + public PropertySourceBuilder putAll(Map values){ + this.properties.putAll(values); + return this; + } + + /** + * Sets the ordinal to be used explicitly (instead evaluating it using {@code tamaya.ordinal}. + * @param ordinal the explicit ordinal to be used. + * @return the bulder for chaining. + */ + public PropertySourceBuilder withOrdinal(int ordinal){ + this.ordinal = ordinal; + return this; + } + + /** + * Puts all values from the given property source. + * @param propertySource the property source, not null. + * @return the bulder for chaining. + */ + public PropertySourceBuilder putAll(PropertySource propertySource){ + this.properties.putAll(propertySource.getProperties()); + return this; + } + + /** + * Creates a new immutable {@link org.apache.tamaya.spi.PropertySource} instance. + * @return a new immutable {@link org.apache.tamaya.spi.PropertySource} instance, never null. + */ + public PropertySource build(){ + return new SimplePropertySource(name, properties); + } + + @Override + public String toString() { + return "PropertySourceBuilder{" + + "ordinal=" + ordinal + + ", name='" + name + '\'' + + ", properties=" + properties + + '}'; + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/f45a5bb5/builder/src/main/java/org/apache/tamaya/builder/SimplePropertySource.java ---------------------------------------------------------------------- diff --git a/builder/src/main/java/org/apache/tamaya/builder/SimplePropertySource.java b/builder/src/main/java/org/apache/tamaya/builder/SimplePropertySource.java new file mode 100644 index 0000000..085bd9a --- /dev/null +++ b/builder/src/main/java/org/apache/tamaya/builder/SimplePropertySource.java @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tamaya.builder; + +import org.apache.tamaya.spi.PropertySource; +import org.apache.tamaya.spi.PropertyValue; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** +* Simple property source implementation using a map. +*/ +public class SimplePropertySource implements PropertySource { + /** The properties. */ + private final Map properties; + /** The source's name. */ + private final String name; + + public SimplePropertySource(String name, Map properties){ + this.properties = new HashMap<>(properties); + this.name = Objects.requireNonNull(name); + } + + @Override + public int getOrdinal(){ + PropertyValue configuredOrdinal = get(TAMAYA_ORDINAL); + if(configuredOrdinal!=null){ + try{ + return Integer.parseInt(configuredOrdinal.getValue()); + } catch(Exception e){ + Logger.getLogger(getClass().getName()).log(Level.WARNING, + "Configured Ordinal is not an int number: " + configuredOrdinal, e); + } + } + return getDefaultOrdinal(); + } + + public int getDefaultOrdinal(){ + return 0; + } + + @Override + public String getName() { + return name; + } + + @Override + public PropertyValue get(String key) { + return null; + } + + @Override + public Map getProperties() { + return this.properties; + } + + @Override + public boolean isScannable() { + return false; + } + + @Override + public String toString(){ + return "SimplePropertySource(name="+name+", numProps="+properties.size()+")"; + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/f45a5bb5/builder/src/main/java/org/apache/tamaya/builder/package-info.java ---------------------------------------------------------------------- diff --git a/builder/src/main/java/org/apache/tamaya/builder/package-info.java b/builder/src/main/java/org/apache/tamaya/builder/package-info.java new file mode 100644 index 0000000..24c86a9 --- /dev/null +++ b/builder/src/main/java/org/apache/tamaya/builder/package-info.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * This package provides + * {@link org.apache.tamaya.builder.ConfigurationBuilder a configuration + * builder} that allows to build a configuration manually without + * using exclusively on the Service Provider Interface API of Tamaya. + * + * @see org.apache.tamaya.builder.ConfigurationBuilder + * @see org.apache.tamaya.Configuration + */ +package org.apache.tamaya.builder; \ No newline at end of file