http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/common/src/test/java/org/apache/tamaya/format/InputStreamFactoryTest.java ---------------------------------------------------------------------- diff --git a/modules/formats/common/src/test/java/org/apache/tamaya/format/InputStreamFactoryTest.java b/modules/formats/common/src/test/java/org/apache/tamaya/format/InputStreamFactoryTest.java new file mode 100644 index 0000000..c05da09 --- /dev/null +++ b/modules/formats/common/src/test/java/org/apache/tamaya/format/InputStreamFactoryTest.java @@ -0,0 +1,145 @@ +/* + * 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.junit.Test; +import org.mockito.ArgumentCaptor; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +public class InputStreamFactoryTest { + + @Test(expected = NullPointerException.class) + public void ctorEnforcesNonNullOriginal() throws IOException { + new InputStreamFactory(null); + } + + @Test + public void givenStreamIsClosedInTryWithResourcesConstruct() throws Exception { + InputStream stream = mock(InputStream.class); + doReturn(34).when(stream).read(); + + InputStreamFactory factory = new InputStreamFactory(stream); + verify(stream).close(); + for (int i = 0; i < 100; i++) { + try (InputStream in = factory.createInputStream()) { + in.read(); + } + } + verify(stream).close(); + } + + @Test + public void callToReadIsNotForwardedCallToWrapped() throws IOException { + InputStream stream = new ByteArrayInputStream(new byte[]{1, 2, 3, 4}); + InputStreamFactory closer = new InputStreamFactory(stream); + byte[] byteArray = new byte[4]; + for (int i = 0; i < 100; i++) { + InputStream is = closer.createInputStream(); + assertThat(is.read(byteArray), equalTo(4)); + } + } + + + @Test + public void callToSkipIsForwardedToWrapped() throws IOException { + InputStream stream = new ByteArrayInputStream(new byte[]{1, 2, 3, 4}); + InputStreamFactory closer = new InputStreamFactory(stream); + for (int i = 0; i < 100; i++) { + InputStream is = closer.createInputStream(); + assertThat(is.skip(2L), equalTo(2L)); + } + } + + + @Test + public void callToAvailableIsNotForwardedToWrapped() throws IOException { + InputStream stream = new ByteArrayInputStream(new byte[]{1, 2, 3, 4}); + InputStreamFactory closer = new InputStreamFactory(stream); + for (int i = 0; i < 100; i++) { + InputStream is = closer.createInputStream(); + assertThat(is.available(), equalTo(4)); + } + } + + @Test + public void callToCloseIsNotForwardedToWrapped() throws IOException { + InputStream stream = new ByteArrayInputStream(new byte[]{1, 2, 3, 4}); + InputStreamFactory closer = new InputStreamFactory(stream); + for (int i = 0; i < 100; i++) { + InputStream is = closer.createInputStream(); + is.close(); + } + } + + @Test + public void callToMarkIsNotForwardedToWrapped() throws IOException { +// ArgumentCaptor<Integer> captor = ArgumentCaptor.forClass(Integer.class); + InputStream stream = new ByteArrayInputStream(new byte[]{1, 2, 3, 4}); + InputStreamFactory closer = new InputStreamFactory(stream); + for (int i = 0; i < 100; i++) { + InputStream is = closer.createInputStream(); + is.mark(2); + } + } + + + @Test + public void callToResetIsNotForwardedToWrapped() throws IOException { + InputStream stream = new ByteArrayInputStream(new byte[]{1, 2, 3, 4}); + InputStreamFactory closer = new InputStreamFactory(stream); + for (int i = 0; i < 100; i++) { + InputStream is = closer.createInputStream(); + is.reset(); + } + } + + @Test + public void callToMarkSupportedIsNotForwardedToWrapped() throws IOException { + InputStream stream = new ByteArrayInputStream(new byte[]{1, 2, 3, 4}); + InputStreamFactory closer = new InputStreamFactory(stream); + for (int i = 0; i < 100; i++) { + InputStream is = closer.createInputStream(); + assertThat(is.markSupported(), is(true)); + } + } + + @Test + public void callToReadIsForwardedToWrapped() throws IOException { + InputStream stream = new ByteArrayInputStream(new byte[]{1, 2, 3, 4}); + InputStreamFactory closer = new InputStreamFactory(stream); + for (int i = 0; i < 100; i++) { + InputStream is = closer.createInputStream(); + assertThat(is.read(), equalTo(1)); + assertThat(is.read(), equalTo(2)); + assertThat(is.read(), equalTo(3)); + assertThat(is.read(), equalTo(4)); + } + } + +}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/common/src/test/resources/Test.ini ---------------------------------------------------------------------- diff --git a/modules/formats/common/src/test/resources/Test.ini b/modules/formats/common/src/test/resources/Test.ini new file mode 100644 index 0000000..906a1e6 --- /dev/null +++ b/modules/formats/common/src/test/resources/Test.ini @@ -0,0 +1,26 @@ +# +# 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. +# + +aGeneralEntry=blabla + +[MySection1] +sectionEntry1=value1 + +[MySection2] +sectionEntry2=value2 \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/common/src/test/resources/Test.properties ---------------------------------------------------------------------- diff --git a/modules/formats/common/src/test/resources/Test.properties b/modules/formats/common/src/test/resources/Test.properties new file mode 100644 index 0000000..ced544b --- /dev/null +++ b/modules/formats/common/src/test/resources/Test.properties @@ -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. +# +aGeneralEntry=blabla +MySection1.sectionEntry1=value1 +MySection2.sectionEntry2=value2 \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/json/pom.xml ---------------------------------------------------------------------- diff --git a/modules/formats/json/pom.xml b/modules/formats/json/pom.xml new file mode 100644 index 0000000..8346231 --- /dev/null +++ b/modules/formats/json/pom.xml @@ -0,0 +1,149 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +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. +--> +<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-json</artifactId> + <name>Apache Tamaya JSON Support</name> + <packaging>bundle</packaging> + <inceptionYear>2015</inceptionYear> + + <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</groupId> + <artifactId>tamaya-core</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>org.apache.tamaya.ext</groupId> + <artifactId>tamaya-formats</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.geronimo.specs</groupId> + <artifactId>geronimo-json_1.0_spec</artifactId> + </dependency> + <dependency> + <groupId>org.apache.johnzon</groupId> + <artifactId>johnzon-core</artifactId> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + </dependency> + <dependency> + <groupId>org.jboss.arquillian.daemon</groupId> + <artifactId>arquillian-daemon-container-managed</artifactId> + </dependency> + <dependency> + <groupId>org.jboss.arquillian.daemon</groupId> + <artifactId>arquillian-daemon-container-common</artifactId> + </dependency> + <dependency> + <groupId>org.jboss.arquillian.daemon</groupId> + <artifactId>arquillian-daemon-main</artifactId> + </dependency> + <dependency> + <groupId>org.jboss.arquillian.daemon</groupId> + <artifactId>arquillian-daemon-protocol-arquillian</artifactId> + </dependency> + <dependency> + <groupId>org.jboss.arquillian.daemon</groupId> + <artifactId>arquillian-daemon-protocol-wire</artifactId> + </dependency> + <dependency> + <groupId>org.jboss.arquillian.daemon</groupId> + <artifactId>arquillian-daemon-server</artifactId> + </dependency> + <dependency> + <groupId>org.jboss.arquillian.junit</groupId> + <artifactId>arquillian-junit-container</artifactId> + </dependency> + <dependency> + <groupId>org.hamcrest</groupId> + <artifactId>java-hamcrest</artifactId> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <artifactId>maven-dependency-plugin</artifactId> + <executions> + <execution> + <id>copyMain</id> + <phase>process-test-sources</phase> + <goals> + <goal>copy</goal> + </goals> + <configuration> + <outputDirectory>${project.build.directory}</outputDirectory> + <overWriteReleases>false</overWriteReleases> + <overWriteSnapshots>false</overWriteSnapshots> + <overWriteIfNewer>true</overWriteIfNewer> + <stripVersion>true</stripVersion> + <artifactItems> + <artifactItem> + <groupId>org.jboss.arquillian.daemon</groupId> + <artifactId>arquillian-daemon-main</artifactId> + </artifactItem> + </artifactItems> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Export-Package> + org.apache.tamaya.json + </Export-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> + + +</project> http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/json/src/main/java/org/apache/tamaya/json/JSONFormat.java ---------------------------------------------------------------------- diff --git a/modules/formats/json/src/main/java/org/apache/tamaya/json/JSONFormat.java b/modules/formats/json/src/main/java/org/apache/tamaya/json/JSONFormat.java new file mode 100644 index 0000000..8bdd414 --- /dev/null +++ b/modules/formats/json/src/main/java/org/apache/tamaya/json/JSONFormat.java @@ -0,0 +1,85 @@ +/* + * 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.json; + +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.InputStream; +import java.net.URL; +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +import javax.json.Json; +import javax.json.JsonException; +import javax.json.JsonObject; +import javax.json.JsonReader; +import javax.json.JsonReaderFactory; + +/** + * Implementation of the {@link org.apache.tamaya.format.ConfigurationFormat} + * able to read configuration properties represented in JSON + * + * @see <a href="http://www.json.org">JSON format specification</a> + */ +public class JSONFormat implements ConfigurationFormat { + /** Property that make Johnzon accept commentc. */ + public static final String JOHNZON_SUPPORTS_COMMENTS_PROP = "org.apache.johnzon.supports-comments"; + /** The reader factory used. */ + private final JsonReaderFactory readerFactory; + + /** + * Constructor, itniaitlizing zhe JSON reader factory. + */ + public JSONFormat(){ + Map<String, Object> config = new HashMap<>(); + config.put(JOHNZON_SUPPORTS_COMMENTS_PROP, true); + this.readerFactory = Json.createReaderFactory(config); + } + + @Override + public String getName() { + return "json"; + } + + @Override + public boolean accepts(URL url) { + return Objects.requireNonNull(url).getPath().endsWith(".json"); + } + + @Override + public ConfigurationData readConfiguration(String resource, InputStream inputStream) { + + try { + final JsonReader reader = this.readerFactory.createReader(inputStream, Charset.forName("UTF-8")); + JsonObject root = reader.readObject(); + HashMap<String, String> values = new HashMap<>(); + JSONVisitor visitor = new JSONVisitor(root, values); + visitor.run(); + return ConfigurationDataBuilder.of(resource, this).addProperties(values) + .build(); + } catch (JsonException e) { + throw new ConfigException("Failed to read data from " + resource, e); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/json/src/main/java/org/apache/tamaya/json/JSONPropertySource.java ---------------------------------------------------------------------- diff --git a/modules/formats/json/src/main/java/org/apache/tamaya/json/JSONPropertySource.java b/modules/formats/json/src/main/java/org/apache/tamaya/json/JSONPropertySource.java new file mode 100644 index 0000000..43cfa73 --- /dev/null +++ b/modules/formats/json/src/main/java/org/apache/tamaya/json/JSONPropertySource.java @@ -0,0 +1,149 @@ +/* + * 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.json; + +import org.apache.tamaya.ConfigException; +import org.apache.tamaya.spi.PropertySource; +import org.apache.tamaya.spi.PropertyValue; + +import java.io.InputStream; +import java.net.URL; +import java.nio.charset.Charset; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.json.Json; +import javax.json.JsonObject; +import javax.json.JsonReaderFactory; +import javax.json.JsonStructure; + +import static java.lang.String.format; + +/** + * Property source based on a JSON file. + */ +public class JSONPropertySource implements PropertySource { + /** Constant for enabling comments in Johnzon. */ + public static final String JOHNZON_SUPPORTS_COMMENTS_PROP = "org.apache.johnzon.supports-comments"; + + /** The underlying resource. */ + private final URL urlResource; + /** The values read. */ + private final Map<String, String> values; + /** The evaluated ordinal. */ + private int ordinal; + /** The JSON reader factory used. */ + private JsonReaderFactory readerFactory = initReaderFactory(); + + /** Initializes the factory to be used for creating readers. */ + private JsonReaderFactory initReaderFactory() { + Map<String, Object> config = new HashMap<>(); + config.put(JOHNZON_SUPPORTS_COMMENTS_PROP, true); + return Json.createReaderFactory(config); + } + + /** + * Constructor, hereby using 0 as the default ordinal. + * @param resource the resource modelled as URL, not null. + */ + public JSONPropertySource(URL resource) { + this(resource, 0); + } + + /** + * Constructor. + * @param resource the resource modelled as URL, not null. + * @param defaultOrdinal the defaultOrdinal to be used. + */ + public JSONPropertySource(URL resource, int defaultOrdinal) { + urlResource = Objects.requireNonNull(resource); + this.ordinal = defaultOrdinal; // may be overriden by read... + this.values = readConfig(urlResource); + if (this.values.containsKey(TAMAYA_ORDINAL)) { + this.ordinal = Integer.parseInt(this.values.get(TAMAYA_ORDINAL)); + } + Map<String, Object> config = new HashMap<>(); + config.put(JOHNZON_SUPPORTS_COMMENTS_PROP, true); + this.readerFactory = Json.createReaderFactory(config); + } + + + @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 ordinal; + } + + @Override + public String getName() { + return urlResource.toExternalForm(); + } + + @Override + public PropertyValue get(String key) { + return PropertyValue.of(key, getProperties().get(key), getName()); + } + + @Override + public Map<String, String> getProperties() { + return Collections.unmodifiableMap(values); + } + + /** + * Reads the configuration. + * @param urlResource soure of the configuration. + * @return the configuration read from the given resource URL. + * @throws ConfigException if resource URL cannot be read. + */ + protected Map<String, String> readConfig(URL urlResource) { + try (InputStream is = urlResource.openStream()) { + JsonStructure root = this.readerFactory.createReader(is, Charset.forName("UTF-8")).read(); + + // Test added. H. Saly, 15. Aug. 2015 + if (!(root instanceof JsonObject)) { + throw new ConfigException("Currently only JSON objects are supported"); + } + + Map<String, String> values = new HashMap<>(); + JSONVisitor visitor = new JSONVisitor((JsonObject)root, values); + visitor.run(); + return values; + } + catch (Throwable t) { + throw new ConfigException(format("Failed to read properties from %s", urlResource.toExternalForm()), t); + } + } + + @Override + public boolean isScannable() { + return true; + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/json/src/main/java/org/apache/tamaya/json/JSONVisitor.java ---------------------------------------------------------------------- diff --git a/modules/formats/json/src/main/java/org/apache/tamaya/json/JSONVisitor.java b/modules/formats/json/src/main/java/org/apache/tamaya/json/JSONVisitor.java new file mode 100644 index 0000000..2135ec5 --- /dev/null +++ b/modules/formats/json/src/main/java/org/apache/tamaya/json/JSONVisitor.java @@ -0,0 +1,119 @@ +/* + * 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.json; + +import org.apache.tamaya.ConfigException; + +import java.util.*; + +import javax.json.JsonArray; +import javax.json.JsonObject; +import javax.json.JsonString; +import javax.json.JsonStructure; +import javax.json.JsonValue; + +/** + * Visitor implementation to read a JSON formatted input source. + */ +class JSONVisitor { + private final JsonObject rootNode; + private final Map<String, String> targetStore; + + JSONVisitor(JsonObject startNode, Map<String, String> target) { + rootNode = startNode; + targetStore = target; + } + + public void run() { + Deque<VisitingContext> stack = new ArrayDeque<>(); + + stack.add(new VisitingContext(rootNode)); + boolean goOn = stack.peek().hasNext(); + + if (goOn) { + do { + Map.Entry<String, JsonValue> current = stack.peek().nextElement(); + + if (!(current.getValue() instanceof JsonStructure)) { + String key = stack.peek().getNSPrefix() + current.getKey(); + String value; + JsonValue jsonValue = current.getValue(); + switch(jsonValue.getValueType()) { + case NULL: value = null; break; + case FALSE: value = Boolean.FALSE.toString(); break; + case TRUE: value = Boolean.TRUE.toString(); break; + case NUMBER: value = jsonValue.toString(); break; + case STRING: value = ((JsonString) jsonValue).getString(); break; + default: + throw new ConfigException("Internal failure while processing JSON document."); + } + + targetStore.put(key, value); + } else if (current.getValue() instanceof JsonObject) { + String key = stack.peek().getNSPrefix() + current.getKey(); + JsonObject node = (JsonObject) current.getValue(); + stack.push(new VisitingContext(node, key)); + } else if (current.getValue() instanceof JsonArray) { + throw new ConfigException("Arrays are not supported at the moment."); + } else { + throw new ConfigException("Internal failure while processing JSON document."); + } + + goOn = stack.peek().hasNext(); + + while (!goOn && stack.size() > 0) { + stack.remove(); + goOn = (stack.size() > 0) && stack.peek().hasNext(); + } + } while (goOn); + } + } + + /** + * Context for a sub context visited. + */ + private static class VisitingContext { + private final String namespace; + private final JsonObject node; + private final Iterator<Map.Entry<String, JsonValue>> elements; + + public VisitingContext(JsonObject node) { + this(node, ""); + } + + public VisitingContext(JsonObject rootNode, String currentNamespace) { + namespace = currentNamespace; + node = rootNode; + elements = node.entrySet().iterator(); + } + + public Map.Entry<String, JsonValue> nextElement() { + return elements.next(); + } + + + public boolean hasNext() { + return elements.hasNext(); + } + + public String getNSPrefix() { + return namespace.isEmpty() ? namespace : namespace + "."; + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/json/src/main/resources/META-INF/services/org.apache.tamaya.format.ConfigurationFormat ---------------------------------------------------------------------- diff --git a/modules/formats/json/src/main/resources/META-INF/services/org.apache.tamaya.format.ConfigurationFormat b/modules/formats/json/src/main/resources/META-INF/services/org.apache.tamaya.format.ConfigurationFormat new file mode 100644 index 0000000..a843cbe --- /dev/null +++ b/modules/formats/json/src/main/resources/META-INF/services/org.apache.tamaya.format.ConfigurationFormat @@ -0,0 +1,19 @@ +# +# 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.json.JSONFormat \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/json/src/test/java/org/apache/tamaya/json/CommonJSONTestCaseCollection.java ---------------------------------------------------------------------- diff --git a/modules/formats/json/src/test/java/org/apache/tamaya/json/CommonJSONTestCaseCollection.java b/modules/formats/json/src/test/java/org/apache/tamaya/json/CommonJSONTestCaseCollection.java new file mode 100644 index 0000000..946878c --- /dev/null +++ b/modules/formats/json/src/test/java/org/apache/tamaya/json/CommonJSONTestCaseCollection.java @@ -0,0 +1,190 @@ +/* + * 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.json; + +import org.apache.tamaya.ConfigException; +import org.apache.tamaya.spi.PropertySource; +import org.apache.tamaya.spi.PropertyValue; +import org.hamcrest.CoreMatchers; +import org.hamcrest.Matchers; +import org.junit.Test; + +import java.net.URL; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasSize; + +/** + * Class with a collection of common test cases each JSON processing + * class must be able to pass. + */ +public abstract class CommonJSONTestCaseCollection { + + abstract PropertySource getPropertiesFrom(URL source) throws Exception; + + @Test + public void canReadNonLatinCharacters() throws Exception { + URL configURL = JSONPropertySourceTest.class + .getResource("/configs/valid/cyrillic.json"); + + assertThat(configURL, Matchers.notNullValue()); + + PropertySource propertySource = getPropertiesFrom(configURL); + + assertThat(propertySource.get("name"), Matchers.notNullValue()); + assertThat(propertySource.get("name").getValue(), equalTo("\u041e\u043b\u0438\u0432\u0435\u0440")); + assertThat(propertySource.get("\u0444\u0430\u043c\u0438\u043b\u0438\u044f"), Matchers.notNullValue()); + assertThat(propertySource.get("\u0444\u0430\u043c\u0438\u043b\u0438\u044f").getValue(), Matchers.equalTo("Fischer")); + } + + @Test + public void canReadNestedStringOnlyJSONConfigFile() throws Exception { + URL configURL = JSONPropertySourceTest.class + .getResource("/configs/valid/simple-nested-string-only-config-1.json"); + + assertThat(configURL, CoreMatchers.notNullValue()); + + PropertySource properties = getPropertiesFrom(configURL); + + assertThat(properties.getProperties().keySet(), hasSize(5)); + + PropertyValue keyB = properties.get("b"); + PropertyValue keyDO = properties.get("d.o"); + PropertyValue keyDP = properties.get("d.p"); + + assertThat(keyB, notNullValue()); + assertThat(keyB.getValue(), equalTo("B")); + assertThat(keyDO, notNullValue()); + assertThat(keyDO.getValue(), equalTo("O")); + assertThat(keyDP, Matchers.notNullValue()); + assertThat(keyDP.getValue(), is("P")); + } + + @Test + public void canReadNestedStringOnlyJSONConfigFileWithObjectInTheMiddle() + throws Exception { + URL configURL = JSONPropertySourceTest.class + .getResource("/configs/valid/simple-nested-string-only-config-2.json"); + + assertThat(configURL, CoreMatchers.notNullValue()); + + PropertySource properties = getPropertiesFrom(configURL); + + assertThat(properties.getProperties().keySet(), hasSize(4)); + + PropertyValue keyA = properties.get("a"); + PropertyValue keyDO = properties.get("b.o"); + PropertyValue keyDP = properties.get("b.p"); + PropertyValue keyC = properties.get("c"); + + assertThat(keyA, notNullValue()); + assertThat(keyA.getValue(), is("A")); + assertThat(keyC, notNullValue()); + assertThat(keyC.getValue(), equalTo("C")); + assertThat(keyDO, notNullValue()); + assertThat(keyDO.getValue(), equalTo("O")); + assertThat(keyDP, notNullValue()); + assertThat(keyDP.getValue(), is("P")); + } + + @Test(expected = ConfigException.class) + public void canHandleIllegalJSONFileWhichContainsAnArray() throws Exception { + URL configURL = JSONPropertySourceTest.class.getResource("/configs/invalid/with-array.json"); + + assertThat(configURL, CoreMatchers.notNullValue()); + + getPropertiesFrom(configURL).getProperties(); + } + + @Test(expected = ConfigException.class) + public void canHandleIllegalJSONFileConsistingOfOneOpeningBracket() throws Exception { + URL configURL = JSONPropertySourceTest.class.getResource("/configs/invalid/only-opening-bracket.json"); + + assertThat(configURL, CoreMatchers.notNullValue()); + + getPropertiesFrom(configURL).getProperties(); + } + + @Test(expected = ConfigException.class) + public void canHandleIllegalJSONFileWhichIsEmpty() throws Exception { + URL configURL = JSONPropertySourceTest.class.getResource("/configs/invalid/empty-file.json"); + + assertThat(configURL, CoreMatchers.notNullValue()); + + getPropertiesFrom(configURL).getProperties(); + } + + @Test + public void priorityInConfigFileOverwriteExplicitlyGivenPriority() throws Exception { + URL configURL = JSONPropertySourceTest.class.getResource("/configs/valid/with-explicit-priority.json"); + + assertThat(configURL, CoreMatchers.notNullValue()); + + PropertySource properties = getPropertiesFrom(configURL); + + assertThat(properties.getOrdinal(), is(16784)); + } + + @Test + public void canReadFlatStringOnlyJSONConfigFile() throws Exception { + URL configURL = JSONPropertySourceTest.class.getResource("/configs/valid/simple-flat-string-only-config.json"); + + assertThat(configURL, CoreMatchers.notNullValue()); + + PropertySource properties = getPropertiesFrom(configURL); + + assertThat(properties.getProperties().keySet(), hasSize(3)); + + PropertyValue keyA = properties.get("a"); + PropertyValue keyB = properties.get("b"); + PropertyValue keyC = properties.get("c"); + + assertThat(keyA, notNullValue()); + assertThat(keyA.getValue(), equalTo("A")); + assertThat(keyB, notNullValue()); + assertThat(keyB.getValue(), is("B")); + assertThat(keyC, notNullValue()); + assertThat(keyC.getValue(), is("C")); + } + + @Test(expected = ConfigException.class) + public void emptyJSONFileResultsInConfigException() throws Exception { + URL configURL = JSONPropertySourceTest.class.getResource("/configs/invalid/empty-file.json"); + + assertThat(configURL, CoreMatchers.notNullValue()); + + PropertySource properties = getPropertiesFrom(configURL); + + properties.getProperties(); + } + + @Test + public void canHandleEmptyJSONObject() throws Exception { + URL configURL = JSONPropertySourceTest.class.getResource("/configs/valid/empty-object-config.json"); + + assertThat(configURL, CoreMatchers.notNullValue()); + + PropertySource properties = getPropertiesFrom(configURL); + + assertThat(properties.getProperties().keySet(), hasSize(0)); + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/json/src/test/java/org/apache/tamaya/json/JSONFormatIT.java ---------------------------------------------------------------------- diff --git a/modules/formats/json/src/test/java/org/apache/tamaya/json/JSONFormatIT.java b/modules/formats/json/src/test/java/org/apache/tamaya/json/JSONFormatIT.java new file mode 100644 index 0000000..851655e --- /dev/null +++ b/modules/formats/json/src/test/java/org/apache/tamaya/json/JSONFormatIT.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tamaya.json; + +import org.apache.tamaya.format.ConfigurationFormat; +import org.apache.tamaya.spi.ServiceContextManager; +import org.junit.Test; + +import java.util.List; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.notNullValue; + +/** + * Integration tests for {@link JSONFormat}. + */ +public class JSONFormatIT { + @Test + public void jsonFormatCanBeFoundViaServiceLoader() throws Exception { + List<ConfigurationFormat> formats = ServiceContextManager.getServiceContext() + .getServices(ConfigurationFormat.class); + + ConfigurationFormat format = null; + for (ConfigurationFormat f : formats) { + if (f instanceof JSONFormat) { + format = f; + break; + } + } + assertThat(format, notNullValue()); + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/json/src/test/java/org/apache/tamaya/json/JSONFormatTest.java ---------------------------------------------------------------------- diff --git a/modules/formats/json/src/test/java/org/apache/tamaya/json/JSONFormatTest.java b/modules/formats/json/src/test/java/org/apache/tamaya/json/JSONFormatTest.java new file mode 100644 index 0000000..9218046 --- /dev/null +++ b/modules/formats/json/src/test/java/org/apache/tamaya/json/JSONFormatTest.java @@ -0,0 +1,75 @@ +/* + * 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.json; + + +import org.apache.tamaya.format.ConfigurationData; +import org.apache.tamaya.format.FlattenedDefaultPropertySource; +import org.apache.tamaya.spi.PropertySource; +import org.junit.Test; + +import java.io.InputStream; +import java.net.URL; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; + +public class JSONFormatTest extends CommonJSONTestCaseCollection { + private final JSONFormat format = new JSONFormat(); + + @Test(expected = NullPointerException.class) + public void acceptsNeedsNonNullParameter() throws Exception { + format.accepts(null); + } + + @Test + public void aNonJSONFileBasedURLIsNotAccepted() throws Exception { + URL url = new URL("file:///etc/service/conf.conf"); + + assertThat(format.accepts(url), is(false)); + } + + @Test + public void aJSONFileBasedURLIsAccepted() throws Exception { + URL url = new URL("file:///etc/service/conf.json"); + + assertThat(format.accepts(url), is(true)); + } + + @Test + public void aHTTPBasedURLIsNotAccepted() throws Exception { + URL url = new URL("http://nowhere.somewhere/conf.json"); + assertThat(format.accepts(url), is(true)); + } + + @Test + public void aFTPBasedURLIsNotAccepted() throws Exception { + URL url = new URL("ftp://nowhere.somewhere/a/b/c/d/conf.json"); + + assertThat(format.accepts(url), is(true)); + } + + @Override + PropertySource getPropertiesFrom(URL source) throws Exception { + try (InputStream is = source.openStream()) { + ConfigurationData data = format.readConfiguration(source.toString(), is); + return new FlattenedDefaultPropertySource(data); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/json/src/test/java/org/apache/tamaya/json/JSONPropertySourceTest.java ---------------------------------------------------------------------- diff --git a/modules/formats/json/src/test/java/org/apache/tamaya/json/JSONPropertySourceTest.java b/modules/formats/json/src/test/java/org/apache/tamaya/json/JSONPropertySourceTest.java new file mode 100644 index 0000000..9892446 --- /dev/null +++ b/modules/formats/json/src/test/java/org/apache/tamaya/json/JSONPropertySourceTest.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tamaya.json; + +import org.apache.tamaya.ConfigException; +import org.apache.tamaya.spi.PropertySource; +import org.hamcrest.CoreMatchers; +import org.junit.Test; + +import java.net.URL; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; + +public class JSONPropertySourceTest extends CommonJSONTestCaseCollection { + + @Test + public void tamayaOrdinalKeywordIsNotPropagatedAsNormalProperty() throws Exception { + URL configURL = JSONPropertySourceTest.class.getResource("/configs/valid/with-explicit-priority.json"); + + assertThat(configURL, CoreMatchers.notNullValue()); + + JSONPropertySource source = new JSONPropertySource(configURL, 4); + assertEquals(source.get(PropertySource.TAMAYA_ORDINAL).getValue(), "16784"); + } + + @Test(expected=ConfigException.class) + public void testDoNotAcceptJsonArrays() throws Exception { + URL configURL = JSONPropertySourceTest.class.getResource("/configs/invalid/array.json"); + + assertThat(configURL, CoreMatchers.notNullValue()); + + new JSONPropertySource(configURL); + } + + @Override + PropertySource getPropertiesFrom(URL source) throws Exception { + return new JSONPropertySource(source); + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/json/src/test/resources/arquillian.xml ---------------------------------------------------------------------- diff --git a/modules/formats/json/src/test/resources/arquillian.xml b/modules/formats/json/src/test/resources/arquillian.xml new file mode 100644 index 0000000..1eeb58b --- /dev/null +++ b/modules/formats/json/src/test/resources/arquillian.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +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. +--> +<arquillian xmlns="http://jboss.org/schema/arquillian" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://jboss.org/schema/arquillian http://jboss.org/schema/arquillian/arquillian_1_0.xsd"> + <container qualifier="daemon" default="true"> + <configuration> + <property name="host">localhost</property> + <property name="port">12346</property> + <property name="serverJarFile">target/arquillian-daemon-main.jar</property> + </configuration> + </container> +</arquillian> http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/json/src/test/resources/configs/invalid/array.json ---------------------------------------------------------------------- diff --git a/modules/formats/json/src/test/resources/configs/invalid/array.json b/modules/formats/json/src/test/resources/configs/invalid/array.json new file mode 100644 index 0000000..0c2058a --- /dev/null +++ b/modules/formats/json/src/test/resources/configs/invalid/array.json @@ -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 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. +*/ +[ + +] \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/json/src/test/resources/configs/invalid/empty-file.json ---------------------------------------------------------------------- diff --git a/modules/formats/json/src/test/resources/configs/invalid/empty-file.json b/modules/formats/json/src/test/resources/configs/invalid/empty-file.json new file mode 100644 index 0000000..f396085 --- /dev/null +++ b/modules/formats/json/src/test/resources/configs/invalid/empty-file.json @@ -0,0 +1,18 @@ +/* +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. +*/ \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/json/src/test/resources/configs/invalid/only-opening-bracket.json ---------------------------------------------------------------------- diff --git a/modules/formats/json/src/test/resources/configs/invalid/only-opening-bracket.json b/modules/formats/json/src/test/resources/configs/invalid/only-opening-bracket.json new file mode 100644 index 0000000..b936f69 --- /dev/null +++ b/modules/formats/json/src/test/resources/configs/invalid/only-opening-bracket.json @@ -0,0 +1,19 @@ +/* +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. +*/ +{ \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/json/src/test/resources/configs/invalid/with-array.json ---------------------------------------------------------------------- diff --git a/modules/formats/json/src/test/resources/configs/invalid/with-array.json b/modules/formats/json/src/test/resources/configs/invalid/with-array.json new file mode 100644 index 0000000..e623e49 --- /dev/null +++ b/modules/formats/json/src/test/resources/configs/invalid/with-array.json @@ -0,0 +1,27 @@ +/* +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. +*/ +{ + "a" : "A", + "b" : { + "c" : "C", + "d" : [ + "1", "2" + ] + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/json/src/test/resources/configs/valid/cyrillic.json ---------------------------------------------------------------------- diff --git a/modules/formats/json/src/test/resources/configs/valid/cyrillic.json b/modules/formats/json/src/test/resources/configs/valid/cyrillic.json new file mode 100644 index 0000000..b9f07b8 --- /dev/null +++ b/modules/formats/json/src/test/resources/configs/valid/cyrillic.json @@ -0,0 +1,22 @@ +/* +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. +*/ +{ + "name" : "ÐливеÑ", + "ÑамилиÑ" : "Fischer" +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/json/src/test/resources/configs/valid/empty-object-config.json ---------------------------------------------------------------------- diff --git a/modules/formats/json/src/test/resources/configs/valid/empty-object-config.json b/modules/formats/json/src/test/resources/configs/valid/empty-object-config.json new file mode 100644 index 0000000..103c28d --- /dev/null +++ b/modules/formats/json/src/test/resources/configs/valid/empty-object-config.json @@ -0,0 +1,20 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy 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. +*/ +{ +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/json/src/test/resources/configs/valid/simple-flat-string-only-config.json ---------------------------------------------------------------------- diff --git a/modules/formats/json/src/test/resources/configs/valid/simple-flat-string-only-config.json b/modules/formats/json/src/test/resources/configs/valid/simple-flat-string-only-config.json new file mode 100644 index 0000000..02e2cd8 --- /dev/null +++ b/modules/formats/json/src/test/resources/configs/valid/simple-flat-string-only-config.json @@ -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. +*/ +{ + "a" : "A", + "b" : "B", + "c" : "C" +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/json/src/test/resources/configs/valid/simple-nested-string-only-config-1.json ---------------------------------------------------------------------- diff --git a/modules/formats/json/src/test/resources/configs/valid/simple-nested-string-only-config-1.json b/modules/formats/json/src/test/resources/configs/valid/simple-nested-string-only-config-1.json new file mode 100644 index 0000000..fb2c4fe --- /dev/null +++ b/modules/formats/json/src/test/resources/configs/valid/simple-nested-string-only-config-1.json @@ -0,0 +1,27 @@ +/* +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. +*/ +{ + "a": "A", + "b": "B", + "c": "C", + "d": { + "o": "O", + "p": "P" + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/json/src/test/resources/configs/valid/simple-nested-string-only-config-2.json ---------------------------------------------------------------------- diff --git a/modules/formats/json/src/test/resources/configs/valid/simple-nested-string-only-config-2.json b/modules/formats/json/src/test/resources/configs/valid/simple-nested-string-only-config-2.json new file mode 100644 index 0000000..b037174 --- /dev/null +++ b/modules/formats/json/src/test/resources/configs/valid/simple-nested-string-only-config-2.json @@ -0,0 +1,26 @@ +/* +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. +*/ +{ + "a" : "A", + "b" : { + "o" : "O", + "p" : "P" + }, + "c" : "C" +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/json/src/test/resources/configs/valid/with-explicit-priority.json ---------------------------------------------------------------------- diff --git a/modules/formats/json/src/test/resources/configs/valid/with-explicit-priority.json b/modules/formats/json/src/test/resources/configs/valid/with-explicit-priority.json new file mode 100644 index 0000000..ed7acc2 --- /dev/null +++ b/modules/formats/json/src/test/resources/configs/valid/with-explicit-priority.json @@ -0,0 +1,25 @@ +/* +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. +*/ +{ + /* + some useful comment here + */ + "tamaya.ordinal" : 16784, + "a" : "A" // another comment +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/formats/pom.xml ---------------------------------------------------------------------- diff --git a/modules/formats/pom.xml b/modules/formats/pom.xml index 990acfc..387d455 100644 --- a/modules/formats/pom.xml +++ b/modules/formats/pom.xml @@ -1,24 +1,22 @@ -<!-- -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"> +<!-- + ~ 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. + --> +<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> @@ -27,62 +25,14 @@ under the License. <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> + <artifactId>tamaya-formats-all</artifactId> + <name>Apache Tamaya Modules - Formats Parent</name> + <packaging>pom</packaging> - <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> + <modules> + <module>common</module> + <module>json</module> + <module>yaml</module> + </modules> - <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/src/main/java/org/apache/tamaya/format/BaseFormatPropertySourceProvider.java ---------------------------------------------------------------------- diff --git a/modules/formats/src/main/java/org/apache/tamaya/format/BaseFormatPropertySourceProvider.java b/modules/formats/src/main/java/org/apache/tamaya/format/BaseFormatPropertySourceProvider.java deleted file mode 100644 index 84d6cfa..0000000 --- a/modules/formats/src/main/java/org/apache/tamaya/format/BaseFormatPropertySourceProvider.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.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/src/main/java/org/apache/tamaya/format/ConfigurationData.java ---------------------------------------------------------------------- diff --git a/modules/formats/src/main/java/org/apache/tamaya/format/ConfigurationData.java b/modules/formats/src/main/java/org/apache/tamaya/format/ConfigurationData.java deleted file mode 100644 index b58d2ab..0000000 --- a/modules/formats/src/main/java/org/apache/tamaya/format/ConfigurationData.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.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 + - '}'; - } - - -}
