This is an automated email from the ASF dual-hosted git repository.
rmannibucau pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/openwebbeans-meecrowave.git
The following commit(s) were added to refs/heads/master by this push:
new dbe6d21 MEECROWAVE-203 adding configuration.complete support for
meecrowave.properties
dbe6d21 is described below
commit dbe6d21304feffab0de729606ee5c4097f5176ed
Author: Romain Manni-Bucau <[email protected]>
AuthorDate: Mon Jul 15 11:31:57 2019 +0200
MEECROWAVE-203 adding configuration.complete support for
meecrowave.properties
---
.../java/org/apache/meecrowave/Meecrowave.java | 26 ++++++-
.../java/org/apache/meecrowave/MeecrowaveTest.java | 86 ++++++++++++++++++++++
.../content/meecrowave-core/configuration.adoc | 6 +-
pom.xml | 2 +-
4 files changed, 116 insertions(+), 4 deletions(-)
diff --git
a/meecrowave-core/src/main/java/org/apache/meecrowave/Meecrowave.java
b/meecrowave-core/src/main/java/org/apache/meecrowave/Meecrowave.java
index 0028c60..748cd6f 100644
--- a/meecrowave-core/src/main/java/org/apache/meecrowave/Meecrowave.java
+++ b/meecrowave-core/src/main/java/org/apache/meecrowave/Meecrowave.java
@@ -2051,8 +2051,9 @@ public class Meecrowave implements AutoCloseable {
public Builder loadFrom(final String resource) {
// load all of those files on the classpath, sorted by ordinal
- Properties config = PropertyLoader.getProperties(resource);
- if (config == null) {
+ Properties config = PropertyLoader.getProperties(resource,
+ sortedProperties -> mergeProperties(resource,
sortedProperties));
+ if (config == null || config.isEmpty()) {
final File file = new File(resource);
if (file.exists()) {
config = new Properties();
@@ -2369,6 +2370,27 @@ public class Meecrowave implements AutoCloseable {
public void setMeecrowaveProperties(final String meecrowaveProperties)
{
this.meecrowaveProperties = meecrowaveProperties;
}
+
+ private Properties mergeProperties(final String resource, final
List<Properties> sortedProperties) {
+ Properties mergedProperties = new Properties();
+ Properties master = null;
+ for (final Properties p : sortedProperties)
+ {
+ if
(Boolean.parseBoolean(p.getProperty("configuration.complete", "false"))) {
+ if (master != null) {
+ throw new IllegalArgumentException("Ambiguous '" +
resource + "', " +
+ "multiple " + resource + " with
configuration.complete=true");
+ }
+ master = p;
+ }
+ mergedProperties.putAll(p);
+ }
+
+ if (master != null) {
+ return master;
+ }
+ return mergedProperties;
+ }
}
public static class ValueTransformers implements Function<String, String> {
diff --git
a/meecrowave-core/src/test/java/org/apache/meecrowave/MeecrowaveTest.java
b/meecrowave-core/src/test/java/org/apache/meecrowave/MeecrowaveTest.java
index a652d76..94916dc 100644
--- a/meecrowave-core/src/test/java/org/apache/meecrowave/MeecrowaveTest.java
+++ b/meecrowave-core/src/test/java/org/apache/meecrowave/MeecrowaveTest.java
@@ -28,6 +28,7 @@ import org.superbiz.app.InterfaceApi;
import org.superbiz.app.RsApp;
import org.superbiz.app.TestJsonEndpoint;
+import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
@@ -35,10 +36,17 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Writer;
+import java.net.MalformedURLException;
import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+import java.nio.charset.StandardCharsets;
+import java.util.Enumeration;
import java.util.Properties;
import java.util.stream.Stream;
+import static java.util.Arrays.asList;
+import static java.util.Collections.enumeration;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@@ -46,6 +54,37 @@ import static org.junit.Assert.fail;
public class MeecrowaveTest {
@Test
+ public void conflictingConfig() throws MalformedURLException {
+ withConfigClassLoader(() -> {
+ try {
+ new Meecrowave.Builder().loadFrom("test.config.properties");
+ fail("should have failed since it conflicts");
+ } catch (final IllegalArgumentException iae) {
+ // ok
+ }
+ }, configUrl("configuration.complete=true\nf=1"),
configUrl("configuration.complete=true\nf=2"));
+ }
+
+ @Test
+ public void masterConfig() throws MalformedURLException {
+ withConfigClassLoader(() -> {
+ final Meecrowave.Builder builder = new Meecrowave.Builder();
+ builder.loadFrom("test.config.properties");
+ assertEquals(1, builder.getHttpPort());
+ }, configUrl("http=2"),
configUrl("configuration.complete=true\nhttp=1"), configUrl("http=3"));
+ }
+
+ @Test
+ public void mergedConfig() throws MalformedURLException {
+ withConfigClassLoader(() -> {
+ final Meecrowave.Builder builder = new Meecrowave.Builder();
+ builder.loadFrom("test.config.properties");
+ assertEquals(2, builder.getHttpPort());
+ assertEquals(4, builder.getHttpsPort());
+ }, configUrl("http=2\nconfiguration.ordinal=2\nhttps=4"),
configUrl("http=3\nconfiguration.ordinal=1"));
+ }
+
+ @Test
public void configBinding() {
final MyConfig config = new Meecrowave.Builder()
.property("my-prefix-port", "1234")
@@ -160,4 +199,51 @@ public class MeecrowaveTest {
@CliOption(name = "my-prefix-bool", description = "")
private boolean bool;
}
+
+ private static URL configUrl(final String content) throws
MalformedURLException {
+ return new URL("memory", null, -1, "test.config.properties", new
MemoryHandler(content));
+ }
+
+ private static void withConfigClassLoader(final Runnable test, final
URL... urls) {
+ final Thread thread = Thread.currentThread();
+ final ClassLoader loader = thread.getContextClassLoader();
+ thread.setContextClassLoader(new ClassLoader(loader) {
+ @Override
+ public Enumeration<URL> getResources(final String name) throws
IOException {
+ return "test.config.properties".equals(name) ?
enumeration(asList(urls)) : super.getResources(name);
+ }
+ });
+ try {
+ test.run();
+ } finally {
+ thread.setContextClassLoader(loader);
+ }
+ }
+
+ private static class MemoryHandler extends URLStreamHandler
+ {
+ private final String content;
+
+ private MemoryHandler(final String content)
+ {
+ this.content = content;
+ }
+
+ @Override
+ protected URLConnection openConnection(final URL u) {
+ return new URLConnection(u)
+ {
+ @Override
+ public void connect()
+ {
+ // no-op
+ }
+
+ @Override
+ public InputStream getInputStream() {
+ return new
ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));
+ }
+ };
+ }
+ }
}
diff --git
a/meecrowave-doc/src/main/jbake/content/meecrowave-core/configuration.adoc
b/meecrowave-doc/src/main/jbake/content/meecrowave-core/configuration.adoc
index c49a74d..06e60e7 100755
--- a/meecrowave-doc/src/main/jbake/content/meecrowave-core/configuration.adoc
+++ b/meecrowave-doc/src/main/jbake/content/meecrowave-core/configuration.adoc
@@ -124,7 +124,11 @@ Finally you can use any dotted attribute to configure the
valve (see example aft
- `configurationCustomizer.x=y` will set `x` to `y` for the customizer
TIP: Out of the box, any `Builder` instance will read `meecrowave.properties`.
-`meecrowave.properties` uses CLI names (without the leading `--`).
+`meecrowave.properties` uses CLI names (without the leading `--`). It loads
all available files from the classpath,
+they are merged using `configuration.ordinal` key (exactly like Apache
OpenWebBeans does for its configuration).
+It also supports `configuration.complete=[true|false]` which enables a single
file to host it with the `true` value
+and will consider this file as the merged result of all potential files found
in the classpath. It is useful to
+avoid an implicit merging and can typically be used in
`conf/meecrowave.properties` in bundle mode.
See link:{context_rootpath}/meecrowave-core/cli.html[CLI] page for the list.
=== Valve configuration
diff --git a/pom.xml b/pom.xml
index 446a8aa..77efdc8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -51,7 +51,7 @@
<junit.version>4.13-beta-3</junit.version>
<tomcat.version>9.0.22</tomcat.version>
- <openwebbeans.version>2.0.11</openwebbeans.version>
+ <openwebbeans.version>2.0.12-SNAPSHOT</openwebbeans.version>
<cxf.version>3.3.2</cxf.version>
<johnzon.version>1.1.13-SNAPSHOT</johnzon.version>
<log4j2.version>2.11.2</log4j2.version>