TAMAYA-189: Moved format and injection modules into separate subtrees.
Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/commit/fe7cd8f1 Tree: http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/tree/fe7cd8f1 Diff: http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/diff/fe7cd8f1 Branch: refs/heads/master Commit: fe7cd8f1bb151a1891196e1899470e5f93abf7e9 Parents: c757d32 Author: anatole <anat...@apache.org> Authored: Sun Oct 30 22:57:31 2016 +0100 Committer: anatole <anat...@apache.org> Committed: Sun Oct 30 22:57:31 2016 +0100 ---------------------------------------------------------------------- modules/formats/common/pom.xml | 88 ++++ .../BaseFormatPropertySourceProvider.java | 154 ++++++ .../apache/tamaya/format/ConfigurationData.java | 206 ++++++++ .../tamaya/format/ConfigurationDataBuilder.java | 219 ++++++++ .../tamaya/format/ConfigurationFormat.java | 103 ++++ .../tamaya/format/ConfigurationFormats.java | 187 +++++++ .../format/FlattenedDefaultPropertySource.java | 118 +++++ .../tamaya/format/InputStreamFactory.java | 89 ++++ .../format/formats/IniConfigurationFormat.java | 95 ++++ .../tamaya/format/formats/PropertiesFormat.java | 71 +++ .../format/formats/PropertiesXmlFormat.java | 69 +++ .../tamaya/format/formats/package-info.java | 23 + .../org/apache/tamaya/format/package-info.java | 28 ++ ...org.apache.tamaya.format.ConfigurationFormat | 21 + .../tamaya/format/ConfigurationFormatsTest.java | 68 +++ .../FlattenedDefaultPropertySourceTest.java | 98 ++++ .../tamaya/format/InputStreamFactoryTest.java | 145 ++++++ .../formats/common/src/test/resources/Test.ini | 26 + .../common/src/test/resources/Test.properties | 21 + modules/formats/json/pom.xml | 149 ++++++ .../java/org/apache/tamaya/json/JSONFormat.java | 85 ++++ .../apache/tamaya/json/JSONPropertySource.java | 149 ++++++ .../org/apache/tamaya/json/JSONVisitor.java | 119 +++++ ...org.apache.tamaya.format.ConfigurationFormat | 19 + .../json/CommonJSONTestCaseCollection.java | 190 +++++++ .../org/apache/tamaya/json/JSONFormatIT.java | 48 ++ .../org/apache/tamaya/json/JSONFormatTest.java | 75 +++ .../tamaya/json/JSONPropertySourceTest.java | 56 +++ .../json/src/test/resources/arquillian.xml | 30 ++ .../test/resources/configs/invalid/array.json | 21 + .../resources/configs/invalid/empty-file.json | 18 + .../configs/invalid/only-opening-bracket.json | 19 + .../resources/configs/invalid/with-array.json | 27 + .../test/resources/configs/valid/cyrillic.json | 22 + .../configs/valid/empty-object-config.json | 20 + .../valid/simple-flat-string-only-config.json | 23 + .../simple-nested-string-only-config-1.json | 27 + .../simple-nested-string-only-config-2.json | 26 + .../configs/valid/with-explicit-priority.json | 25 + modules/formats/pom.xml | 104 +--- .../BaseFormatPropertySourceProvider.java | 154 ------ .../apache/tamaya/format/ConfigurationData.java | 206 -------- .../tamaya/format/ConfigurationDataBuilder.java | 219 -------- .../tamaya/format/ConfigurationFormat.java | 103 ---- .../tamaya/format/ConfigurationFormats.java | 187 ------- .../format/FlattenedDefaultPropertySource.java | 118 ----- .../tamaya/format/InputStreamFactory.java | 89 ---- .../format/formats/IniConfigurationFormat.java | 95 ---- .../tamaya/format/formats/PropertiesFormat.java | 71 --- .../format/formats/PropertiesXmlFormat.java | 69 --- .../tamaya/format/formats/package-info.java | 23 - .../org/apache/tamaya/format/package-info.java | 28 -- ...org.apache.tamaya.format.ConfigurationFormat | 21 - .../tamaya/format/ConfigurationFormatsTest.java | 68 --- .../FlattenedDefaultPropertySourceTest.java | 98 ---- .../tamaya/format/InputStreamFactoryTest.java | 145 ------ modules/formats/src/test/resources/Test.ini | 26 - .../formats/src/test/resources/Test.properties | 21 - modules/formats/yaml/pom.xml | 119 +++++ .../java/org/apache/tamaya/json/YAMLFormat.java | 156 ++++++ .../apache/tamaya/json/YAMLPropertySource.java | 100 ++++ ...org.apache.tamaya.format.ConfigurationFormat | 19 + .../org/apache/tamaya/json/YAMLFormatTest.java | 73 +++ .../tamaya/json/YAMLPropertySourceTest.java | 54 ++ .../test/resources/configs/valid/contact.yaml | 46 ++ .../resources/configs/valid/test-with-prio.yaml | 39 ++ .../src/test/resources/configs/valid/test.yaml | 35 ++ modules/injection-api/pom.xml | 81 --- .../tamaya/inject/api/BaseDynamicValue.java | 125 ----- .../org/apache/tamaya/inject/api/Config.java | 93 ---- .../tamaya/inject/api/ConfigAutoInject.java | 36 -- .../inject/api/ConfigDefaultSections.java | 44 -- .../inject/api/ConfiguredItemSupplier.java | 41 -- .../apache/tamaya/inject/api/DynamicValue.java | 161 ------ .../tamaya/inject/api/InjectionUtils.java | 127 ----- .../apache/tamaya/inject/api/LoadPolicy.java | 42 -- .../org/apache/tamaya/inject/api/NoConfig.java | 36 -- .../apache/tamaya/inject/api/UpdatePolicy.java | 40 -- .../tamaya/inject/api/WithConfigOperator.java | 45 -- .../inject/api/WithPropertyConverter.java | 46 -- .../apache/tamaya/inject/api/package-info.java | 22 - .../tamaya/inject/spi/ConfiguredField.java | 68 --- .../tamaya/inject/spi/ConfiguredMethod.java | 70 --- .../tamaya/inject/spi/ConfiguredType.java | 63 --- modules/injection/cdi-ee/pom.xml | 226 +++++++++ .../integration/cdi/CDIAwareServiceContext.java | 169 +++++++ .../integration/cdi/CDIConfiguredField.java | 77 +++ .../integration/cdi/CDIConfiguredMethod.java | 77 +++ .../integration/cdi/CDIConfiguredType.java | 94 ++++ .../integration/cdi/ConfigurationExtension.java | 290 +++++++++++ .../integration/cdi/ConfigurationProducer.java | 147 ++++++ .../integration/cdi/DefaultDynamicValue.java | 499 +++++++++++++++++++ .../cdi/ServiceLoaderServiceContext.java | 151 ++++++ .../integration/cdi/TamayaCDIIntegration.java | 52 ++ .../src/main/resources/META-INF/beans.xml | 19 + .../javax.enterprise.inject.spi.Extension | 19 + .../org.apache.tamaya.spi.ServiceContext | 38 ++ ...onfigurationProducerFailedInjectionTest.java | 33 ++ .../cdi/ConfigurationProducerTest.java | 168 +++++++ .../cdi/ConfigurationResolverTest.java | 112 +++++ .../integration/cdi/EnvironmentsTest.java | 83 +++ .../integration/cdi/InterpolationTest.java | 62 +++ .../integration/cdi/NotFoundNoDefault.java | 78 +++ .../src/test/resources/META-INF/beans.xml | 19 + .../META-INF/javaconfiguration.properties | 32 ++ .../cdi-ee/src/test/resources/base.properties | 32 ++ .../cdi-ee/src/test/resources/cert.properties | 20 + .../cdi-ee/src/test/resources/dev.properties | 19 + .../cdi-ee/src/test/resources/prod.properties | 20 + .../cdi-ee/src/test/resources/qa.properties | 20 + .../cdi-ee/src/test/resources/test.properties | 20 + modules/injection/cdi-se/pom.xml | 212 ++++++++ .../integration/cdi/CDIAwareServiceContext.java | 169 +++++++ .../cdi/DefaultConfigurationContext.java | 296 +++++++++++ .../cdi/DefaultConfigurationContextBuilder.java | 152 ++++++ .../tamaya/integration/cdi/EnumConverter.java | 71 +++ .../cdi/PropertyConverterManager.java | 427 ++++++++++++++++ .../integration/cdi/SEInjectorCDIExtension.java | 112 +++++ .../cdi/ServiceLoaderServiceContext.java | 151 ++++++ .../integration/cdi/TamayaCDIIntegration.java | 52 ++ .../integration/cdi/TamayaConfigProvider.java | 55 ++ .../cdi/config/ConfiguredVetoExtension.java | 42 ++ .../src/main/resources/META-INF/beans.xml | 24 + .../javax.enterprise.inject.spi.Extension | 20 + .../org.apache.tamaya.spi.ServiceContext | 19 + .../tamaya/integration/cdi/ConfiguredClass.java | 112 +++++ .../tamaya/integration/cdi/ConfiguredTest.java | 83 +++ .../tamaya/integration/cdi/InjectedClass.java | 62 +++ .../cdi/cfg/ProvidedPropertySource.java | 67 +++ .../integration/cdi/cfg/TestConfigProvider.java | 45 ++ .../integration/cdi/cfg/TestPropertySource.java | 79 +++ .../src/test/resources/META-INF/beans.xml | 24 + .../META-INF/javaconfiguration.properties | 20 + modules/injection/injection-api/pom.xml | 81 +++ .../tamaya/inject/api/BaseDynamicValue.java | 125 +++++ .../org/apache/tamaya/inject/api/Config.java | 93 ++++ .../tamaya/inject/api/ConfigAutoInject.java | 36 ++ .../inject/api/ConfigDefaultSections.java | 44 ++ .../inject/api/ConfiguredItemSupplier.java | 41 ++ .../apache/tamaya/inject/api/DynamicValue.java | 161 ++++++ .../tamaya/inject/api/InjectionUtils.java | 127 +++++ .../apache/tamaya/inject/api/LoadPolicy.java | 42 ++ .../org/apache/tamaya/inject/api/NoConfig.java | 36 ++ .../apache/tamaya/inject/api/UpdatePolicy.java | 40 ++ .../tamaya/inject/api/WithConfigOperator.java | 45 ++ .../inject/api/WithPropertyConverter.java | 46 ++ .../apache/tamaya/inject/api/package-info.java | 22 + .../tamaya/inject/spi/ConfiguredField.java | 68 +++ .../tamaya/inject/spi/ConfiguredMethod.java | 70 +++ .../tamaya/inject/spi/ConfiguredType.java | 63 +++ modules/injection/pom.xml | 123 ++--- .../tamaya/inject/ConfigurationInjection.java | 42 -- .../tamaya/inject/ConfigurationInjector.java | 94 ---- .../ConfigTemplateInvocationHandler.java | 73 --- .../inject/internal/ConfiguredFieldImpl.java | 170 ------- .../inject/internal/ConfiguredSetterMethod.java | 139 ------ .../inject/internal/ConfiguredTypeImpl.java | 237 --------- .../internal/DefaultConfigurationInjector.java | 179 ------- .../inject/internal/DefaultDynamicValue.java | 498 ------------------ .../tamaya/inject/internal/InjectionHelper.java | 244 --------- .../apache/tamaya/inject/internal/Utils.java | 128 ----- .../tamaya/inject/internal/package-info.java | 22 - .../org/apache/tamaya/inject/package-info.java | 22 - ...g.apache.tamaya.inject.ConfigurationInjector | 19 - .../java/annottext/AnnotatedConfigBean.java | 78 --- .../java/annottext/AnnotatedConfigTemplate.java | 47 -- .../java/annottext/NonAnnotatedConfigBean.java | 45 -- .../tamaya/inject/TamayaInjectionTest.java | 87 ---- .../tamaya/inject/TestPropertySource.java | 68 --- .../internal/DefaultDynamicValueTest.java | 315 ------------ .../org.apache.tamaya.spi.PropertySource | 19 - modules/injection/standalone/pom.xml | 104 ++++ .../tamaya/inject/ConfigurationInjection.java | 42 ++ .../tamaya/inject/ConfigurationInjector.java | 94 ++++ .../ConfigTemplateInvocationHandler.java | 73 +++ .../inject/internal/ConfiguredFieldImpl.java | 170 +++++++ .../inject/internal/ConfiguredSetterMethod.java | 139 ++++++ .../inject/internal/ConfiguredTypeImpl.java | 237 +++++++++ .../internal/DefaultConfigurationInjector.java | 179 +++++++ .../inject/internal/DefaultDynamicValue.java | 498 ++++++++++++++++++ .../tamaya/inject/internal/InjectionHelper.java | 244 +++++++++ .../apache/tamaya/inject/internal/Utils.java | 128 +++++ .../tamaya/inject/internal/package-info.java | 22 + .../org/apache/tamaya/inject/package-info.java | 22 + ...g.apache.tamaya.inject.ConfigurationInjector | 19 + .../java/annottext/AnnotatedConfigBean.java | 78 +++ .../java/annottext/AnnotatedConfigTemplate.java | 47 ++ .../java/annottext/NonAnnotatedConfigBean.java | 45 ++ .../tamaya/inject/TamayaInjectionTest.java | 87 ++++ .../tamaya/inject/TestPropertySource.java | 68 +++ .../internal/DefaultDynamicValueTest.java | 315 ++++++++++++ .../org.apache.tamaya.spi.PropertySource | 19 + modules/json/pom.xml | 149 ------ .../java/org/apache/tamaya/json/JSONFormat.java | 85 ---- .../apache/tamaya/json/JSONPropertySource.java | 149 ------ .../org/apache/tamaya/json/JSONVisitor.java | 119 ----- ...org.apache.tamaya.format.ConfigurationFormat | 19 - .../json/CommonJSONTestCaseCollection.java | 190 ------- .../org/apache/tamaya/json/JSONFormatIT.java | 48 -- .../org/apache/tamaya/json/JSONFormatTest.java | 75 --- .../tamaya/json/JSONPropertySourceTest.java | 56 --- modules/json/src/test/resources/arquillian.xml | 30 -- .../test/resources/configs/invalid/array.json | 21 - .../resources/configs/invalid/empty-file.json | 18 - .../configs/invalid/only-opening-bracket.json | 19 - .../resources/configs/invalid/with-array.json | 27 - .../test/resources/configs/valid/cyrillic.json | 22 - .../configs/valid/empty-object-config.json | 20 - .../valid/simple-flat-string-only-config.json | 23 - .../simple-nested-string-only-config-1.json | 27 - .../simple-nested-string-only-config-2.json | 26 - .../configs/valid/with-explicit-priority.json | 25 - modules/pom.xml | 4 +- modules/yaml/pom.xml | 119 ----- .../java/org/apache/tamaya/json/YAMLFormat.java | 156 ------ .../apache/tamaya/json/YAMLPropertySource.java | 100 ---- ...org.apache.tamaya.format.ConfigurationFormat | 19 - .../org/apache/tamaya/json/YAMLFormatTest.java | 73 --- .../tamaya/json/YAMLPropertySourceTest.java | 54 -- .../test/resources/configs/valid/contact.yaml | 46 -- .../resources/configs/valid/test-with-prio.yaml | 39 -- .../src/test/resources/configs/valid/test.yaml | 35 -- 222 files changed, 12315 insertions(+), 7370 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/common/pom.xml ---------------------------------------------------------------------- diff --git a/modules/formats/common/pom.xml b/modules/formats/common/pom.xml new file mode 100644 index 0000000..93f4bd2 --- /dev/null +++ b/modules/formats/common/pom.xml @@ -0,0 +1,88 @@ +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy current the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.tamaya.ext</groupId> + <artifactId>tamaya-formats-all</artifactId> + <version>0.3-incubating-SNAPSHOT</version> + <relativePath>..</relativePath> + </parent> + <artifactId>tamaya-formats</artifactId> + <name>Apache Tamaya Modules Formats</name> + <packaging>bundle</packaging> + + <properties> + <jdkVersion>1.7</jdkVersion> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.tamaya</groupId> + <artifactId>tamaya-api</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.tamaya.ext</groupId> + <artifactId>tamaya-resources</artifactId> + <version>${project.version}</version> + </dependency> + <!-- Test scope only, do not create a code dependency! --> + <dependency> + <groupId>org.apache.tamaya</groupId> + <artifactId>tamaya-core</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.hamcrest</groupId> + <artifactId>java-hamcrest</artifactId> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Export-Package> + org.apache.tamaya.format, + org.apache.tamaya.format.formats + </Export-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> +</project> http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/common/src/main/java/org/apache/tamaya/format/BaseFormatPropertySourceProvider.java ---------------------------------------------------------------------- diff --git a/modules/formats/common/src/main/java/org/apache/tamaya/format/BaseFormatPropertySourceProvider.java b/modules/formats/common/src/main/java/org/apache/tamaya/format/BaseFormatPropertySourceProvider.java new file mode 100644 index 0000000..84d6cfa --- /dev/null +++ b/modules/formats/common/src/main/java/org/apache/tamaya/format/BaseFormatPropertySourceProvider.java @@ -0,0 +1,154 @@ +/* + * 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.format; + +import org.apache.tamaya.spi.PropertySource; +import org.apache.tamaya.spi.PropertySourceProvider; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Enumeration; +import java.util.List; +import java.util.Objects; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Implementation of a {@link PropertySourceProvider} that reads configuration from some given resource paths + * and using the given formats. The resource path are resolved as classpath resources. This can be changed by + * overriding {@link #getPropertySources()}. + * For each resource found the configuration formats passed get a chance to read the resource, if they succeed the + * result is taken as the providers PropertySources to be exposed. + */ +public abstract class BaseFormatPropertySourceProvider implements PropertySourceProvider { + /** + * The logger used. + */ + private static final Logger LOG = Logger.getLogger(BaseFormatPropertySourceProvider.class.getName()); + /** + * The config formats supported for the given location/resource paths. + */ + private final List<ConfigurationFormat> configFormats = new ArrayList<>(); + /** + * The paths to be evaluated. + */ + private final Collection<URL> paths = new ArrayList<>(); + + /** + * Creates a new instance. + * + * @param formats the formats to be used, not null, not empty. + * @param paths the paths to be resolved, not null, not empty. + */ + public BaseFormatPropertySourceProvider( + List<ConfigurationFormat> formats, + URL... paths) { + this.configFormats.addAll(Objects.requireNonNull(formats)); + this.paths.addAll(Arrays.asList(Objects.requireNonNull(paths))); + } + + /** + * Creates a new instance, hereby using the current thread context classloader, or if not available the classloader + * that loaded this class. + * @param formats the formats to be used, not null, not empty. + * @param paths the paths to be resolved, not null, not empty. + */ + public BaseFormatPropertySourceProvider( + List<ConfigurationFormat> formats, String... paths) { + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + if(cl==null){ + cl = getClass().getClassLoader(); + } + this.configFormats.addAll(Objects.requireNonNull(formats)); + for(String path:paths) { + Enumeration<URL> urls; + try { + urls = cl.getResources(path); + } catch (IOException e) { + LOG.log(Level.WARNING, "Failed to read resource: " + path, e); + continue; + } + while(urls.hasMoreElements()) { + this.paths.add(urls.nextElement()); + } + } + } + + /** + * Creates a new instance. + * + * @param classLoader the ClassLoader to be used, not null, not empty. + * @param formats the formats to be used, not null, not empty. + * @param paths the paths to be resolved, not null, not empty. + */ + public BaseFormatPropertySourceProvider( + List<ConfigurationFormat> formats, + ClassLoader classLoader, String... paths) { + this.configFormats.addAll(Objects.requireNonNull(formats)); + for(String path:paths) { + Enumeration<URL> urls; + try { + urls = classLoader.getResources(path); + } catch (IOException e) { + LOG.log(Level.WARNING, "Failed to read resource: " + path, e); + continue; + } + while(urls.hasMoreElements()) { + this.paths.add(urls.nextElement()); + } + } + } + + + /** + * Method to create a {@link org.apache.tamaya.spi.PropertySource} based on the given entries read. + * + * @param data the configuration data, not null. + * @return the {@link org.apache.tamaya.spi.PropertySource} instance ready to be registered. + */ + protected abstract Collection<PropertySource> getPropertySources(ConfigurationData data); + + /** + * This method does dynamically resolve the paths using the current ClassLoader set. If no ClassLoader was + * explcitly set during creation the current Thread context ClassLoader is used. If none of the supported + * formats is able to parse a resource a WARNING log is written. + * + * @return the PropertySources successfully read + */ + @Override + public Collection<PropertySource> getPropertySources() { + List<PropertySource> propertySources = new ArrayList<>(); + for (URL res : this.paths) { + try(InputStream is = res.openStream()) { + for (ConfigurationFormat format : configFormats) { + ConfigurationData data = format.readConfiguration(res.toString(), is); + propertySources.addAll(getPropertySources(data)); + } + } catch (Exception e) { + LOG.log(Level.WARNING, "Failed to put resource based config: " + res, e); + } + } + return propertySources; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/common/src/main/java/org/apache/tamaya/format/ConfigurationData.java ---------------------------------------------------------------------- diff --git a/modules/formats/common/src/main/java/org/apache/tamaya/format/ConfigurationData.java b/modules/formats/common/src/main/java/org/apache/tamaya/format/ConfigurationData.java new file mode 100644 index 0000000..b58d2ab --- /dev/null +++ b/modules/formats/common/src/main/java/org/apache/tamaya/format/ConfigurationData.java @@ -0,0 +1,206 @@ +/* + * 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.format; + +import java.util.*; + +/** + * <p>Data that abstracts the data read from a configuration resources using a certain format. The data can be divided + * into different sections, similar to ini-files. Herebey different sections the best map to entries with different + * priorities to be applied, when integrated into PropertySource instances.</p> + * New instances of this class can be created using a {@link org.apache.tamaya.format.ConfigurationDataBuilder}. + * <h3>Implementation Specification</h3> + * This class is + * <ul> + * <li>immutable</li> + * <li>thread-safe</li> + * </ul> + */ +public final class ConfigurationData { + /** + * The properties of the default section (no name). + */ + private Map<String, String> defaultProperties; + /** + * A normalized flattened set of this configuration data. + */ + private Map<String, String> combinedProperties; + /** + * The sections read. + */ + private Map<String, Map<String, String>> namedSections; + /** The format instance used to read this instance. */ + private final ConfigurationFormat format; + /** The resource read. */ + private final String resource; + + + /** + * COnstructor used by builder. + * @param builder the builder instance passing the read configuration data. + */ + ConfigurationData(ConfigurationDataBuilder builder){ + this.format = builder.format; + this.resource = builder.resource; + if (builder.defaultProperties != null) { + this.defaultProperties = new HashMap<>(); + this.defaultProperties.putAll(builder.defaultProperties); + } + if (builder.combinedProperties != null) { + this.combinedProperties = new HashMap<>(); + this.combinedProperties.putAll(builder.combinedProperties); + } + if (builder.namedSections != null) { + this.namedSections = new HashMap<>(); + this.namedSections.putAll(builder.namedSections); + } + if (this.combinedProperties == null || this.combinedProperties.isEmpty()) { + this.combinedProperties = new HashMap<>(); + this.combinedProperties.putAll(getDefaultProperties()); + // popuilate it with sections... + for (String sectionName : getSectionNames()) { + Map<String, String> section = getSection(sectionName); + for (Map.Entry<String, String> en : section.entrySet()) { + String key = sectionName + '.' + en.getKey(); + combinedProperties.put(key, en.getValue()); + } + } + } + } + + /** + * Get the {@link org.apache.tamaya.format.ConfigurationFormat} that read this data. + * @return the {@link org.apache.tamaya.format.ConfigurationFormat} that read this data, never null. + */ + public ConfigurationFormat getFormat(){ + return format; + } + + /** + * Get the resource from which this data was read. + * @return the resource from which this data was read, never null. + */ + public String getResource(){ + return resource; + } + + /** + * Access an immutable Set of all present section names, including the default section (if any). + * @return the set of present section names, never null. + */ + public Set<String> getSectionNames() { + if (namedSections == null) { + return Collections.emptySet(); + } + return namedSections.keySet(); + } + + /** + * Get a section's data. + * @param name the section name, not null. + * @return the data of this section, or null, if no such section exists. + */ + public Map<String, String> getSection(String name) { + return this.namedSections.get(name); + } + + /** + * Convenience accessor for accessing the default section. + * @return the default section's data, or null, if no such section exists. + */ + public Map<String, String> getDefaultProperties() { + if (defaultProperties == null) { + return Collections.emptyMap(); + } + return defaultProperties; + } + + /** + * Get combined properties for this config data instance. If + * + * @return the normalized properties. + */ + public Map<String, String> getCombinedProperties() { + if (combinedProperties == null) { + return Collections.emptyMap(); + } + return combinedProperties; + } + + /** + * Accessor used for easily creating a new builder based on a given data instance. + * + * @return the data contained, never null. + */ + public Map<String, Map<String, String>> getSections() { + if (namedSections == null) { + return Collections.emptyMap(); + } + return namedSections; + } + + /** + * Immutable accessor to ckeck, if there are default properties present. + * + * @return true, if default properties are present. + */ + public boolean hasDefaultProperties() { + return this.defaultProperties != null && !this.defaultProperties.isEmpty(); + } + + /** + * Immutable accessor to ckeck, if there are combined properties set. + * + * @return true, if combined properties are set. + */ + public boolean hasCombinedProperties() { + return this.combinedProperties != null && !this.combinedProperties.isEmpty(); + } + + /** + * Immutable accessor to ckeck, if there are named sections present. + * + * @return true, if at least one named section is present. + */ + private boolean hasSections() { + return this.namedSections != null && !this.namedSections.isEmpty(); + } + + /** + * Checks if no properties are contained in this data item. + * + * @return true, if no properties are contained in this data item. + */ + public boolean isEmpty() { + return !hasCombinedProperties() && !hasDefaultProperties() && !hasSections(); + } + + @Override + public String toString() { + return "ConfigurationData{" + + "format=" + format + + ", default properties=" + defaultProperties + + ", combined properties=" + combinedProperties + + ", sections=" + namedSections + + ", resource=" + resource + + '}'; + } + + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/common/src/main/java/org/apache/tamaya/format/ConfigurationDataBuilder.java ---------------------------------------------------------------------- diff --git a/modules/formats/common/src/main/java/org/apache/tamaya/format/ConfigurationDataBuilder.java b/modules/formats/common/src/main/java/org/apache/tamaya/format/ConfigurationDataBuilder.java new file mode 100644 index 0000000..da5fa35 --- /dev/null +++ b/modules/formats/common/src/main/java/org/apache/tamaya/format/ConfigurationDataBuilder.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.tamaya.format; + +import java.util.*; + + +/** + * Builder for creating {@link org.apache.tamaya.format.ConfigurationData} instances. This class is not thread-safe. + */ +public final class ConfigurationDataBuilder { + + /** The format instance used to read this instance. */ + final ConfigurationFormat format; + /** The resource read. */ + final String resource; + /** + * The properties of the default section (no name). + */ + Map<String, String> defaultProperties; + /** + * A normalized flattened set of this configuration data. + */ + Map<String, String> combinedProperties; + /** + * The sections read. + */ + Map<String, Map<String, String>> namedSections; + + /** + * Private constructor. + * @param resource the configuration resource URL, not null. + * @param format the format that read this data, not null. + */ + private ConfigurationDataBuilder(String resource, ConfigurationFormat format){ + this.format = Objects.requireNonNull(format); + this.resource = Objects.requireNonNull(resource); + } + + /** + * Creates a new instance. + * @param resource the configuration resource URL, not null. + * @param format the format that read this data, not null. + * @return new instance of this class. + */ + public static ConfigurationDataBuilder of(String resource, ConfigurationFormat format){ + return new ConfigurationDataBuilder(resource, format); + } + + /** + * Creates a new instance. + * @param data an existing ConfigurationData instances used to initialize the builder. + * @return new instance of this class from the given configuration. + */ + public static ConfigurationDataBuilder of(ConfigurationData data){ + ConfigurationDataBuilder b = new ConfigurationDataBuilder(data.getResource(), data.getFormat()); + if (data.hasDefaultProperties()) { + b.getDefaultProperties().putAll(data.getDefaultProperties()); + } + if (data.hasCombinedProperties()) { + b.getCombinedProperties().putAll(data.getCombinedProperties()); + } + if (!data.getSections().isEmpty()) { + b.getSections().putAll(data.getSections()); + } + return b; + } + + /** + * Adds (empty) sections,if they are not yet existing. Already existing sections will not be touched. + * @param sections the new sections to put. + * @return the builder for chaining. + */ + public ConfigurationDataBuilder addSections(String... sections){ + for (String section : sections) { + if (!getSections().containsKey(section)) { + getSections().put(section, new HashMap<String, String>()); + } + } + return this; + } + + /** + * Adds a single entry to a target section. + * @param section the target section (will be created if not existing). + * @param key the entry's key + * @param value the entry's value + * @return the builder for chaining. + */ + public ConfigurationDataBuilder addSectionProperty(String section, String key, String value) { + Map<String, String> map = getSections().get(section); + if (map == null) { + map = new HashMap<>(); + getSections().put(section, map); + } + map.put(key, value); + return this; + } + + /** + * Adds a single entry to the <i>default</i> section. + * @param key the entry's key + * @param value the entry's value + * @return the builder for chaining. + */ + public ConfigurationDataBuilder addProperty(String key, String value) { + getDefaultProperties().put(key, value); + return this; + } + + /** + * Adds the given entries to the given section, all existing values will be overridden. + * @param section the target section (will be created if not existing). + * @param properties the entry's data + * @return the builder for chaining. + */ + public ConfigurationDataBuilder addSectionProperties(String section, Map<String, String> properties) { + Map<String, String> map = getSections().get(section); + if (map == null) { + map = new HashMap<>(); + getSections().put(section, map); + } + map.putAll(properties); + return this; + } + + /** + * Adds the given entries to the <i>default</i> section, all existing values will be overridden. + * @param properties the entry's data + * @return the builder for chaining. + */ + public ConfigurationDataBuilder addProperties(Map<String, String> properties) { + getDefaultProperties().putAll(properties); + return this; + } + + /** + * Sets the given entries as the <i>combined</i> properties map, all existing properties of the + * combined map will be overridden. + * + * @param properties the entry's data + * @return the builder for chaining. + */ + public ConfigurationDataBuilder setCombinedProperties(Map<String, String> properties) { + this.combinedProperties = new HashMap<>(properties); + return this; + } + + /** + * Access the current default section, if not present a new instance is initialized. + * + * @return the current default section, never null. + */ + public Map<String, String> getDefaultProperties() { + if (defaultProperties == null) { + defaultProperties = new HashMap<>(); + } + return defaultProperties; + } + + /** + * Access the current combined properties, if not present a new instance is initialized. + * + * @return the current combined properties, never null. + */ + public Map<String, String> getCombinedProperties() { + if (combinedProperties == null) { + combinedProperties = new HashMap<>(); + } + return combinedProperties; + } + + /** + * Access the current named sections, if not present a new instance is initialized. + * + * @return the current named sections, never null. + */ + public Map<String, Map<String, String>> getSections() { + if (namedSections == null) { + namedSections = new HashMap<>(); + } + return namedSections; + } + + /** + * Builds a new {@link org.apache.tamaya.format.ConfigurationData} instance. + * @return a new {@link org.apache.tamaya.format.ConfigurationData} instance, not null. + */ + public ConfigurationData build(){ + return new ConfigurationData(this); + } + + @Override + public String toString() { + return "ConfigurationDataBuilder{" + + "format=" + format + + ", default properties=" + defaultProperties + + ", sections=" + namedSections + + ", combined properties=" + combinedProperties + + ", resource=" + resource + + '}'; + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/common/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java ---------------------------------------------------------------------- diff --git a/modules/formats/common/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java b/modules/formats/common/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java new file mode 100644 index 0000000..997ef3a --- /dev/null +++ b/modules/formats/common/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java @@ -0,0 +1,103 @@ +/* + * 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.format; + +import java.io.InputStream; +import java.net.URL; + +/** + * <p>Implementations current this class encapsulate the mechanism how to read a + * resource including interpreting the format correctly (e.g. xml vs. + * properties vs. ini). In most cases file only contains entries of the same priority, which would then + * result in only one {@link org.apache.tamaya.spi.PropertySource}. Complex file formats, however, may contain entries + * of different priorities. In this cases, each ordinal type found typically is returned as a separate section so the + * consuming {@link org.apache.tamaya.spi.PropertySourceProvider} implementation can distribute the different part to + * individual {@link org.apache.tamaya.spi.PropertySource}s.</p> + * + * <h3>Implementation Requirements</h3> + * Implementations of this type must be + * <ul> + * <li>thread-safe</li> + * </ul> + */ +public interface ConfigurationFormat { + + /** + * Get a unique name of the format. This name can be used to access the format. + * @return the (unique) format's name, never null and not empty. + */ + String getName(); + + /** + * Allows the format to examine the given resource, e.g. for a matching file ending. Only, if a format accepts an + * URL, it will be tried for reading the configuration. + * @param url the url to read the configuration data from (could be a file, a server location, a classpath + * resource or something else, not null. + * @return true, if this format accepts the given URL for reading. + */ + boolean accepts(URL url); + + /** + * Reads a configuration from an URL, hereby parsing the given {@link java.io.InputStream}. Dependening on + * the capabilities of the format the returned {@link org.apache.tamaya.format.ConfigurationData} may contain + * different levels of data: + * <ul> + * <li>Only a <i>default</i> section is returned, since the configuration format does not support + * hierarchies. This is the case for properties and xml properties.</li> + * <li>Hierarchical formats such as INI, XML and JSON can map each node to a section. Each section + * can have its own key/value pairs. This allows to map also complex formats in a generic way. A + * format implementation should then additionally flatten the whole data and store it in a accessible as + * {@link ConfigurationData#getCombinedProperties()}. This allows to use the properties as inout to a default mapping, + * which is always appropriate as long as no other semnatics + * are defined in the concrete target scenario.</li> + * <li>More complex custom scenarios should map their configuration data read into different + * sections. Typically the data will be mapped into different {@link org.apache.tamaya.spi.PropertySource} + * instances with different ordinal levels. As an example imagine a custom format that contains sections + * 'defaults', 'global-defaults', 'application', 'server-overrides'.</li> + * <li>Alternate formats</li> + * </ul> + * + * Summarizing implementations common formats should always provide + * <ul> + * <li>the data organized in sections as useful for the given format. If data is organized in one section, it + * should be mapped into the DEFAULT section.</li> + * <li>Formats that do provide multiple sections, should always provide a FLATTENED section as well, where + * all the data is organized as a flattened key/value pairs, enabling a generic mapping to a + * {@link org.apache.tamaya.spi.PropertySource}.</li> + * </ul> + * + * If the configuration format only contains entries of one ordinal type, normally only one single + * instance of PropertySource is returned (the corresponding key/values should end up in the DEFAULT section). + * Nevertheless custom formats may contain different sections or parts, + * where each part maps to a different target ordinal (eg defaults, domain config and app config). In the + * ladder case multiple PropertySources can be returned, each one with its own ordinal and the corresponding + * entries. + * @see org.apache.tamaya.spi.PropertySource + * @param resource a descriptive name for the resource, since an InputStream does not have any) + * @param inputStream the inputStream to read the configuration data from (could be a file, a server location, a classpath + * resource or something else. + * @return the corresponding {@link ConfigurationData} containing sections/properties read, never {@code null}. + * @throws org.apache.tamaya.ConfigException if parsing of the input fails. + */ + ConfigurationData readConfiguration(String resource, InputStream inputStream); + + //X TODO Add support to access a default format to see a correct formatting + //X String getFormatExample(); + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/common/src/main/java/org/apache/tamaya/format/ConfigurationFormats.java ---------------------------------------------------------------------- diff --git a/modules/formats/common/src/main/java/org/apache/tamaya/format/ConfigurationFormats.java b/modules/formats/common/src/main/java/org/apache/tamaya/format/ConfigurationFormats.java new file mode 100644 index 0000000..bc8aabd --- /dev/null +++ b/modules/formats/common/src/main/java/org/apache/tamaya/format/ConfigurationFormats.java @@ -0,0 +1,187 @@ +/* + * 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.format; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.apache.tamaya.spi.ServiceContextManager; + +/** + * Small accessor and management class dealing with {@link org.apache.tamaya.format.ConfigurationFormat} + * instances. + */ +public final class ConfigurationFormats { + /** + * The logger used. + */ + private static final Logger LOG = Logger.getLogger(ConfigurationFormats.class.getName()); + + /** + * Singleton constructor. + */ + private ConfigurationFormats() { + } + + /** + * Get all currently available formats, ordered by priority. + * + * @return the currently available formats, never null. + */ + public static List<ConfigurationFormat> getFormats() { + return ServiceContextManager.getServiceContext().getServices(ConfigurationFormat.class); + } + + /** + * Get all currently available formats, ordered by priority. + * + * @param formatNames available formats to be ordered. + * @return the currently available formats, never null. + */ + public static List<ConfigurationFormat> getFormats(String... formatNames) { + final List<ConfigurationFormat> result = new ArrayList<>(); + final Set<String> names = new HashSet<>(Arrays.asList(formatNames)); + for (final ConfigurationFormat f : getFormats()) { + if (names.contains(f.getName())) { + result.add(f); + } + } + return result; + } + + // Activate for JDK 8... +// /** +// * Get all currently available formats, ordered by priority. +// * +// * @return the currently available formats, never null. +// */ +// public static List<ConfigurationFormat> getFormats(Predicate<String> namePredicate) { +// List<ConfigurationFormat> result = new ArrayList<>(); +// for(ConfigurationFormat f:getFormats()){ +// if(namePredicate.test(f.getName()){ +// result.add(f); +// } +// } +// return result; +// } + + /** + * Get all currently available formats, ordered by priority. + * + * @param url source to read configuration from. + * @return the currently available formats, never null. + */ + public static List<ConfigurationFormat> getFormats(final URL url) { + final List<ConfigurationFormat> formats = getFormats(); + final List<ConfigurationFormat> result = new ArrayList<>(); + for (final ConfigurationFormat f : formats) { + if (f.accepts(url)) { + result.add(f); + } + } + return result; + } + + /** + * Tries to read configuration data from a given URL, hereby traversing all known formats in order of precedence. + * Hereby the formats are first filtered to check if the URL is acceptable, before the input is being parsed. + * + * @param url the url from where to read, not null. + * @return the ConfigurationData read, or null. + * @throws IOException if the resource cannot be read. + */ + public static ConfigurationData readConfigurationData(final URL url) throws IOException { + final List<ConfigurationFormat> formats = getFormats(url); + return readConfigurationData(url, formats.toArray(new ConfigurationFormat[formats.size()])); + } + + /** + * Tries to read configuration data from a given URL, hereby explicitly trying all given formats in order. + * + * @param url the url from where to read, not null. + * @param formats the formats to try. + * @return the ConfigurationData read, or null. + * @throws IOException if the resource cannot be read. + */ + public static ConfigurationData readConfigurationData(URL url, ConfigurationFormat... formats) throws IOException { + return readConfigurationData(url.toString(), url.openStream(), formats); + } + + /** + * @param urls the urls from where to read, not null. + * @param formats the formats to try. + * @return the {@link org.apache.tamaya.format.ConfigurationData} of the files successfully decoded by the + * given formats. + */ + public static Collection<ConfigurationData> getPropertySources(Collection<URL> urls, ConfigurationFormat... formats) { + final List<ConfigurationData> dataRead = new ArrayList<>(); + for (final URL url : urls) { + try { + final ConfigurationData data = readConfigurationData(url, formats); + if (data != null) { + dataRead.add(data); + } + } catch (final Exception e) { + LOG.log(Level.SEVERE, "Error reading file: " + url.toExternalForm(), e); + } + } + return dataRead; + } + + /** + * Tries to read configuration data from a given URL, hereby explicitly trying all given formats in order. + * + * @param resource a descriptive name for the resource, since an InputStream does not have any + * @param inputStream the inputStream from where to read, not null. + * @param formats the formats to try. + * @return the ConfigurationData read, or null. + * @throws IOException if the resource cannot be read. + */ + public static ConfigurationData readConfigurationData(String resource, InputStream inputStream, + ConfigurationFormat... formats) throws IOException { + Objects.requireNonNull(inputStream); + Objects.requireNonNull(resource); + try(InputStreamFactory isFactory = new InputStreamFactory(inputStream)) { + for (final ConfigurationFormat format : formats) { + try (InputStream is = isFactory.createInputStream()) { + final ConfigurationData data = format.readConfiguration(resource, is); + if (data != null) { + return data; + } + } catch (final Exception e) { + LOG.log(Level.INFO, + "Format " + format.getClass().getName() + " failed to read resource " + resource, e); + } + } + } + return null; + } + + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/common/src/main/java/org/apache/tamaya/format/FlattenedDefaultPropertySource.java ---------------------------------------------------------------------- diff --git a/modules/formats/common/src/main/java/org/apache/tamaya/format/FlattenedDefaultPropertySource.java b/modules/formats/common/src/main/java/org/apache/tamaya/format/FlattenedDefaultPropertySource.java new file mode 100644 index 0000000..9d2097f --- /dev/null +++ b/modules/formats/common/src/main/java/org/apache/tamaya/format/FlattenedDefaultPropertySource.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.format; + +import org.apache.tamaya.spi.PropertySource; +import org.apache.tamaya.spi.PropertyValue; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Flattened default PropertySource that uses the flattened config data read from an URL by a + * ${@link org.apache.tamaya.format.ConfigurationFormat}. + */ +public class FlattenedDefaultPropertySource implements PropertySource { + private static final Logger LOG = Logger.getLogger(FlattenedDefaultPropertySource.class.getName()); + private final Map<String, String> properties; + private final ConfigurationData data; + private int defaultOrdinal = 0; + + + /* + * Constructor, uses hereby the flattened config data read from an URL by a + * ${@link org.apache.tamaya.format.ConfigurationFormat}, and if not present falls back to the default section. + */ + public FlattenedDefaultPropertySource(ConfigurationData data) { + this.properties = populateData(data); + this.data = data; + } + + /* + * Constructor, uses hereby the flattened config data read from an URL by a + * ${@link org.apache.tamaya.format.ConfigurationFormat}, and if not present falls back to the default section. + */ + public FlattenedDefaultPropertySource(int defaultOrdinal, ConfigurationData data) { + this.properties = populateData(data); + this.data = data; + this.defaultOrdinal = defaultOrdinal; + } + + protected Map<String, String> populateData(ConfigurationData data) { + Map<String, String> result = data.getCombinedProperties(); + if (result.isEmpty()) { + result = data.getDefaultProperties(); + } + if (result.isEmpty()) { + result = new HashMap<>(); + } + if(result.isEmpty()){ + for (String section : data.getSectionNames()) { + Map<String,String> sectionMap = data.getSection(section); + for(Map.Entry<String,String> en: sectionMap.entrySet()){ + result.put(section + '.' + en.getKey(), en.getValue()); + } + } + } + return Collections.unmodifiableMap(result); + } + + @Override + public String getName() { + String name = this.properties.get("[meta].name"); + if (name == null) { + name = this.data.getResource(); + } + if (name == null) { + name = getClass().getSimpleName(); + } + return name; + } + + @Override + public int getOrdinal() { + String ordinalValue = this.properties.get(PropertySource.TAMAYA_ORDINAL); + if (ordinalValue != null) { + try { + return Integer.parseInt(ordinalValue.trim()); + } catch (Exception e) { + LOG.log(Level.WARNING, "Failed to parse Tamaya ordinal from " + data.getResource(), e); + } + } + return defaultOrdinal; + } + + @Override + public PropertyValue get(String key) { + return PropertyValue.of(key, properties.get(key), getName()); + } + + @Override + public Map<String, String> getProperties() { + return properties; + } + + @Override + public boolean isScannable() { + return true; + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/common/src/main/java/org/apache/tamaya/format/InputStreamFactory.java ---------------------------------------------------------------------- diff --git a/modules/formats/common/src/main/java/org/apache/tamaya/format/InputStreamFactory.java b/modules/formats/common/src/main/java/org/apache/tamaya/format/InputStreamFactory.java new file mode 100644 index 0000000..912dd08 --- /dev/null +++ b/modules/formats/common/src/main/java/org/apache/tamaya/format/InputStreamFactory.java @@ -0,0 +1,89 @@ +/* + * 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.format; + +import java.io.*; +import java.util.Objects; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Wrapper for a given {@link InputStream} to be able to close + * it via the try-with-resources construct of Java 7. + * + * <h1>Usage example</h1> + * + * <pre> + * public void readIt(InputStream inputStream) { + * try (InputStream is = new ParallelInputStream(inputStream) { + * // Consume the stream + * } + * } + * </pre> + */ +public class InputStreamFactory implements Closeable { + private static final Logger LOG = Logger.getLogger(InputStreamFactory.class.getName()); + + private byte[] data; + + /** + * Creates a new InputStreamFactory. + * + * @param original the InputStream to be read for extract its data into memory. + * @throws IOException if thrown by the original during read. + */ + public InputStreamFactory(InputStream original) throws IOException { + Objects.requireNonNull(original); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + byte[] bytes = new byte[256]; + try { + int read = original.read(bytes); + while (read > 0) { + bos.write(bytes, 0, read); + read = original.read(bytes); + } + this.data = bos.toByteArray(); + } finally { + try { + original.close(); + } catch (IOException e) { + LOG.log(Level.FINEST, "Error closing stream: " + original, e); + } + } + } + + /** + * Creates a new InputStream with the same data as provided by the InputStream passed on factory creation. + * + * @return a new InputStream , never null. + * @throws IOException if no data is available. + */ + public InputStream createInputStream() throws IOException { + byte[] bytes = this.data; + if (bytes == null) { + throw new IOException("InputStreamFactory is closed."); + } + return new ByteArrayInputStream(bytes); + } + + @Override + public void close() throws IOException { + this.data = null; + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/common/src/main/java/org/apache/tamaya/format/formats/IniConfigurationFormat.java ---------------------------------------------------------------------- diff --git a/modules/formats/common/src/main/java/org/apache/tamaya/format/formats/IniConfigurationFormat.java b/modules/formats/common/src/main/java/org/apache/tamaya/format/formats/IniConfigurationFormat.java new file mode 100644 index 0000000..fe27ba7 --- /dev/null +++ b/modules/formats/common/src/main/java/org/apache/tamaya/format/formats/IniConfigurationFormat.java @@ -0,0 +1,95 @@ +/* + * 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.format.formats; + +import org.apache.tamaya.ConfigException; +import org.apache.tamaya.format.ConfigurationData; +import org.apache.tamaya.format.ConfigurationDataBuilder; +import org.apache.tamaya.format.ConfigurationFormat; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Implements a ini file format. + */ +public class IniConfigurationFormat implements ConfigurationFormat { + + /** + * The logger. + */ + private final static Logger LOG = Logger.getLogger(IniConfigurationFormat.class.getName()); + + @Override + public String getName() { + return "ini"; + } + + @Override + public boolean accepts(URL url) { + String fileName = url.getFile(); + return fileName.endsWith(".ini") || fileName.endsWith(".INI"); + } + + @Override + public ConfigurationData readConfiguration(String resource, InputStream inputStream) { + ConfigurationDataBuilder builder = ConfigurationDataBuilder.of(resource, this); + try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"))) { + String line = reader.readLine(); + int lineNum = 0; + String section = null; + while (line != null) { + lineNum++; + line = line.trim(); + if (line.isEmpty()) { + line = reader.readLine(); + continue; + } + if (line.startsWith("[")) { + int end = line.indexOf(']'); + if (end < 0) { + throw new ConfigException( + "Invalid INI-Format, ']' expected, at " + lineNum + " in " + resource); + } + section = line.substring(1, end); + } else if (line.trim().startsWith("#")) { + // comment + } else { + int sep = line.indexOf('='); + String key = line.substring(0, sep); + String value = line.substring(sep + 1); + if (section != null) { + builder.addSectionProperty(section, key, value); + } else { + builder.addProperty(key, value); + } + } + line = reader.readLine(); + } + return builder.build(); + } catch (Exception e) { + LOG.log(Level.SEVERE, "Could not read configuration: " + resource, e); + } + return null; + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/common/src/main/java/org/apache/tamaya/format/formats/PropertiesFormat.java ---------------------------------------------------------------------- diff --git a/modules/formats/common/src/main/java/org/apache/tamaya/format/formats/PropertiesFormat.java b/modules/formats/common/src/main/java/org/apache/tamaya/format/formats/PropertiesFormat.java new file mode 100644 index 0000000..35cef77 --- /dev/null +++ b/modules/formats/common/src/main/java/org/apache/tamaya/format/formats/PropertiesFormat.java @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tamaya.format.formats; + +import org.apache.tamaya.format.ConfigurationData; +import org.apache.tamaya.format.ConfigurationDataBuilder; +import org.apache.tamaya.format.ConfigurationFormat; + +import java.io.InputStream; +import java.net.URL; +import java.util.Map; +import java.util.Objects; +import java.util.Properties; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Implementation of a {@link org.apache.tamaya.format.ConfigurationFormat} for -properties files. + * + * @see java.util.Properties#load(java.io.InputStream) + */ +public class PropertiesFormat implements ConfigurationFormat { + /** + * The logger. + */ + private final static Logger LOG = Logger.getLogger(PropertiesFormat.class.getName()); + + + @Override + public String getName() { + return "properties"; + } + + @Override + public boolean accepts(URL url) { + String fileName = url.getFile(); + return fileName.endsWith(".properties") || fileName.endsWith(".PROPERTIES") || + fileName.endsWith(".conf") || fileName.endsWith(".CONF"); + } + + @SuppressWarnings("unchecked") + @Override + public ConfigurationData readConfiguration(String resource, InputStream inputStream) { + Objects.requireNonNull(inputStream); + Objects.requireNonNull(resource); + try { + final Properties p = new Properties(); + p.load(inputStream); + return ConfigurationDataBuilder.of(resource, this).addProperties(Map.class.cast(p)).build(); + } catch (Exception e) { + LOG.log(Level.FINEST, "Failed to read config from resource: " + resource, e); + } + return null; + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/common/src/main/java/org/apache/tamaya/format/formats/PropertiesXmlFormat.java ---------------------------------------------------------------------- diff --git a/modules/formats/common/src/main/java/org/apache/tamaya/format/formats/PropertiesXmlFormat.java b/modules/formats/common/src/main/java/org/apache/tamaya/format/formats/PropertiesXmlFormat.java new file mode 100644 index 0000000..c47b6f6 --- /dev/null +++ b/modules/formats/common/src/main/java/org/apache/tamaya/format/formats/PropertiesXmlFormat.java @@ -0,0 +1,69 @@ +/* + * 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.format.formats; + +import org.apache.tamaya.format.ConfigurationData; +import org.apache.tamaya.format.ConfigurationDataBuilder; +import org.apache.tamaya.format.ConfigurationFormat; + +import java.io.InputStream; +import java.net.URL; +import java.util.*; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Implementation of a {@link org.apache.tamaya.format.ConfigurationFormat} for xml property + * files. + * + * @see java.util.Properties#loadFromXML(java.io.InputStream) + */ +public class PropertiesXmlFormat implements ConfigurationFormat { + /** + * The logger. + */ + private final static Logger LOG = Logger.getLogger(PropertiesXmlFormat.class.getName()); + + @Override + public String getName() { + return "xml-properties"; + } + + @Override + public boolean accepts(URL url) { + String fileName = url.getFile(); + return fileName.endsWith(".xml") || fileName.endsWith(".XML"); + } + + @SuppressWarnings("unchecked") + @Override + public ConfigurationData readConfiguration(String resource, InputStream inputStream) { + Objects.requireNonNull(inputStream); + Objects.requireNonNull(resource); + + try { + final Properties p = new Properties(); + p.loadFromXML(inputStream); + return ConfigurationDataBuilder.of(resource, this).addProperties(Map.class.cast(p)).build(); + } catch (Exception e) { + LOG.log(Level.FINEST, "Failed to read config from resource: " + resource, e); + } + return null; + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/common/src/main/java/org/apache/tamaya/format/formats/package-info.java ---------------------------------------------------------------------- diff --git a/modules/formats/common/src/main/java/org/apache/tamaya/format/formats/package-info.java b/modules/formats/common/src/main/java/org/apache/tamaya/format/formats/package-info.java new file mode 100644 index 0000000..db8987d --- /dev/null +++ b/modules/formats/common/src/main/java/org/apache/tamaya/format/formats/package-info.java @@ -0,0 +1,23 @@ +/* + * 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 implementtion of {@link org.apache.tamaya.format.ConfigurationFormat} + * for properties, xml-properties and ini files. + */ +package org.apache.tamaya.format.formats; \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/common/src/main/java/org/apache/tamaya/format/package-info.java ---------------------------------------------------------------------- diff --git a/modules/formats/common/src/main/java/org/apache/tamaya/format/package-info.java b/modules/formats/common/src/main/java/org/apache/tamaya/format/package-info.java new file mode 100644 index 0000000..39b5f0b --- /dev/null +++ b/modules/formats/common/src/main/java/org/apache/tamaya/format/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 an abstraction for parsing a configuration + * from an input strem, called {@link org.apache.tamaya.format.ConfigurationFormat} + * and corresponding helper artifacts. + * + * @see org.apache.tamaya.format.ConfigurationFormat + * @see org.apache.tamaya.format.ConfigurationData + * @see org.apache.tamaya.format.ConfigurationFormats + */ +package org.apache.tamaya.format; \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/common/src/main/resources/META-INF/services/org.apache.tamaya.format.ConfigurationFormat ---------------------------------------------------------------------- diff --git a/modules/formats/common/src/main/resources/META-INF/services/org.apache.tamaya.format.ConfigurationFormat b/modules/formats/common/src/main/resources/META-INF/services/org.apache.tamaya.format.ConfigurationFormat new file mode 100644 index 0000000..96e898f --- /dev/null +++ b/modules/formats/common/src/main/resources/META-INF/services/org.apache.tamaya.format.ConfigurationFormat @@ -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.tamaya.format.formats.IniConfigurationFormat +org.apache.tamaya.format.formats.PropertiesFormat +org.apache.tamaya.format.formats.PropertiesXmlFormat \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/common/src/test/java/org/apache/tamaya/format/ConfigurationFormatsTest.java ---------------------------------------------------------------------- diff --git a/modules/formats/common/src/test/java/org/apache/tamaya/format/ConfigurationFormatsTest.java b/modules/formats/common/src/test/java/org/apache/tamaya/format/ConfigurationFormatsTest.java new file mode 100644 index 0000000..0839714 --- /dev/null +++ b/modules/formats/common/src/test/java/org/apache/tamaya/format/ConfigurationFormatsTest.java @@ -0,0 +1,68 @@ +/* + * 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.format; + +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * Tests for {@link org.apache.tamaya.format.ConfigurationFormats}. + */ +public class ConfigurationFormatsTest { + + @org.junit.Test + public void testGetFormats() throws Exception { + List<ConfigurationFormat> formats = ConfigurationFormats.getFormats(); + assertNotNull(formats); + assertEquals(formats.size(), 3); + } + + @org.junit.Test + public void testReadConfigurationData() throws Exception { + List<ConfigurationFormat> formats = ConfigurationFormats.getFormats(getClass().getResource("/Test.ini")); + assertNotNull(formats); + assertEquals(formats.size(), 1); + formats = ConfigurationFormats.getFormats(getClass().getResource("/Test.properties")); + assertNotNull(formats); + assertEquals(formats.size(), 1); +// formats = ConfigurationFormats.getFormats(getClass().getResource("/Test.xml")); +// assertNotNull(formats); +// assertEquals(formats.size(), 1); + + } + + @org.junit.Test + public void testReadConfigurationData_URL() throws Exception { + ConfigurationData data = ConfigurationFormats.readConfigurationData(getClass().getResource("/Test.ini")); + assertNotNull(data); + data = ConfigurationFormats.readConfigurationData(getClass().getResource("/Test.properties")); + assertNotNull(data); + } + + @org.junit.Test + public void testReadConfigurationData2() throws Exception { + List<ConfigurationFormat> formats = ConfigurationFormats.getFormats(); + ConfigurationData data = ConfigurationFormats.readConfigurationData(getClass().getResource("/Test.ini"), + formats.toArray(new ConfigurationFormat[formats.size()])); + assertNotNull(data); + System.out.println(data); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/common/src/test/java/org/apache/tamaya/format/FlattenedDefaultPropertySourceTest.java ---------------------------------------------------------------------- diff --git a/modules/formats/common/src/test/java/org/apache/tamaya/format/FlattenedDefaultPropertySourceTest.java b/modules/formats/common/src/test/java/org/apache/tamaya/format/FlattenedDefaultPropertySourceTest.java new file mode 100644 index 0000000..adc94f6 --- /dev/null +++ b/modules/formats/common/src/test/java/org/apache/tamaya/format/FlattenedDefaultPropertySourceTest.java @@ -0,0 +1,98 @@ +/* + * 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.format; + +import org.apache.tamaya.format.formats.PropertiesFormat; +import org.apache.tamaya.spi.PropertySource; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +/** + * Tests for {@link org.apache.tamaya.format.FlattenedDefaultPropertySource}. + */ +public class FlattenedDefaultPropertySourceTest { + + @Test + public void testGetName() throws Exception { + FlattenedDefaultPropertySource ps = new FlattenedDefaultPropertySource(createConfigurationData("test1")); + assertEquals("test1", ps.getName()); + } + + private ConfigurationData createConfigurationData(String sourceName) { + return ConfigurationDataBuilder.of(sourceName, new PropertiesFormat()) + .addProperty("a", "aValue").addSectionProperty("section1", "sectionKey1", "sectionValue11") + .addSections("section1", "section12") + .addSectionProperty("section2", "sectionKey1", "sectionValue21").build(); + } + + private ConfigurationData createConfigurationData(String sourceName, int ordinal) { + return ConfigurationDataBuilder.of(sourceName, new PropertiesFormat()) + .addProperty("a", "aValue").addSectionProperty("section1", "sectionKey1", "sectionValue11") + .addSections("section1", "section12").addProperty(PropertySource.TAMAYA_ORDINAL, String.valueOf(ordinal)) + .addSectionProperty("section2", "sectionKey1", "sectionValue21").build(); + } + + private ConfigurationData createConfigurationDataNoDefault(String sourceName) { + return ConfigurationDataBuilder.of(sourceName, new PropertiesFormat()) + .addSectionProperty("section1", "sectionKey1", "sectionValue11") + .addSections("section1", "section12") + .addSectionProperty("section2", "sectionKey1", "sectionValue21").build(); + } + + @Test + public void testGetOrdinal() throws Exception { + FlattenedDefaultPropertySource ps = new FlattenedDefaultPropertySource(createConfigurationData("test1", 11)); + assertEquals(11, ps.getOrdinal()); + } + + @Test + public void testGet() throws Exception { + FlattenedDefaultPropertySource ps = new FlattenedDefaultPropertySource(createConfigurationData("test2")); + assertEquals("aValue", ps.get("a").get("a")); + assertNotNull(ps.get("section1.sectionKey1").get("section1.sectionKey1")); + assertNotNull(ps.get("section2.sectionKey1").get("section2.sectionKey1")); + assertNull(ps.get("sectionKey1")); + ps = new FlattenedDefaultPropertySource(createConfigurationDataNoDefault("test2")); + assertEquals("sectionValue11", ps.get("section1.sectionKey1").get("section1.sectionKey1")); + assertEquals("sectionValue21", ps.get("section2.sectionKey1").get("section2.sectionKey1")); + assertNull(ps.get("a")); + assertNull(ps.get("section1")); + } + + @Test + public void testGetProperties() throws Exception { + FlattenedDefaultPropertySource ps = new FlattenedDefaultPropertySource(createConfigurationData("test3")); + assertNotNull(ps.getProperties()); + assertEquals("aValue", ps.getProperties().get("a")); + assertNotNull(ps.getProperties().get("section1.sectionKey1")); + assertNotNull(ps.getProperties().get("section2.sectionKey1")); + assertNull(ps.getProperties().get("section1.sectionKey2")); + assertNull(ps.getProperties().get("section2.sectionKey2")); + assertNull(ps.getProperties().get("sectionKey1")); + assertNull(ps.getProperties().get("sectionKey2")); + ps = new FlattenedDefaultPropertySource(createConfigurationDataNoDefault("test3")); + assertNotNull(ps.getProperties()); + assertEquals("sectionValue11", ps.getProperties().get("section1.sectionKey1")); + assertEquals("sectionValue21", ps.getProperties().get("section2.sectionKey1")); + assertNull(ps.get("section1")); + } +} \ No newline at end of file