Merge pull request #29 from rmannibucau/rmannibucau/KARAF-6907

[KARAF-6907] interpolate config admin values (even if simpler than th…
diff --git a/winegrower-core/src/main/java/org/apache/winegrower/service/DefaultConfigurationAdmin.java b/winegrower-core/src/main/java/org/apache/winegrower/service/DefaultConfigurationAdmin.java
index 18639ce..d7a149d 100644
--- a/winegrower-core/src/main/java/org/apache/winegrower/service/DefaultConfigurationAdmin.java
+++ b/winegrower-core/src/main/java/org/apache/winegrower/service/DefaultConfigurationAdmin.java
@@ -62,7 +62,7 @@
     private final Collection<ConfigurationListener> configurationListeners;
 
     public DefaultConfigurationAdmin(final Map<String, String> providedConfiguration,
-            final Collection<ConfigurationListener> configurationListeners) {
+                                     final Collection<ConfigurationListener> configurationListeners) {
         this.providedConfiguration = providedConfiguration;
         this.configurationListeners = configurationListeners;
     }
@@ -181,7 +181,7 @@
         private final Set<ConfigurationAttribute> attributes = new HashSet<>();
 
         private DefaultConfiguration(final Map<String, String> configRegistry, final String factoryPid, final String pid,
-                final String location, final String name) {
+                                     final String location, final String name) {
             this.configRegistry = configRegistry;
             this.factoryPid = factoryPid;
             this.pid = pid;
@@ -226,6 +226,11 @@
                 }
             }
 
+            final Map<String, String> placeholders = new HashMap<>(Map.class.cast(properties));
+            placeholders.putAll(Map.class.cast(System.getProperties()));
+            placeholders.putAll(System.getenv());
+            final Substitutor substitutor = new Substitutor(placeholders);
+
             // and finally from system properties and env variables
             // (env is for the machine so less precise than system props so set first)
             final String envPrefix = prefix.toUpperCase(ROOT).replace('.', '_');
@@ -242,15 +247,20 @@
                         //     A_B_C_1=dummy
                         // but when there key is not ambiguous (all lowercase) it is simpler to set (key=foobar):
                         //     A_B_C_FOOBAR=dummy
+                        final String value = System.getenv(key);
                         properties.put(
                                 ofNullable(System.getenv(key + "_NAME")).orElseGet(() -> k.toLowerCase(ROOT)),
-                                System.getenv(key));
+                                value.contains("${") && value.contains("}") ? substitutor.replace(value) : value);
                     });
 
             System.getProperties().stringPropertyNames().stream()
                     .filter(it -> it.startsWith(prefix))
-                    .forEach(key -> properties.put(key.substring(prefix.length()), System.getProperty(key)));
-
+                    .forEach(key -> {
+                        final String value = System.getProperty(key);
+                        properties.put(
+                                key.substring(prefix.length()),
+                                value.contains("${") && value.contains("}") ? substitutor.replace(value) : value);
+                    });
 
             // ensure the factoryPid/pid is there if exists
             ofNullable(pid).ifPresent(v -> properties.putIfAbsent("service.pid", v));
@@ -359,9 +369,13 @@
             }
             final Map<String, String> placeholders = new HashMap<>(Map.class.cast(properties));
             placeholders.putAll(Map.class.cast(System.getProperties()));
+            placeholders.putAll(System.getenv());
             final Substitutor substitutor = new Substitutor(placeholders);
             return properties.stringPropertyNames().stream().collect(toMap(identity(),
-                    it -> it.contains("${") && it.contains("}") ? substitutor.replace(it) : properties.getProperty(it)));
+                    it -> {
+                        final String value = properties.getProperty(it);
+                        return value.contains("${") && value.contains("}") ? substitutor.replace(value) : value;
+                    }));
         }
     }
 
diff --git a/winegrower-core/src/test/java/org/apache/winegrower/service/DefaultConfigurationAdminTest.java b/winegrower-core/src/test/java/org/apache/winegrower/service/DefaultConfigurationAdminTest.java
index 681a6a6..2b58ec0 100644
--- a/winegrower-core/src/test/java/org/apache/winegrower/service/DefaultConfigurationAdminTest.java
+++ b/winegrower-core/src/test/java/org/apache/winegrower/service/DefaultConfigurationAdminTest.java
@@ -45,6 +45,17 @@
     };
 
     @Test
+    @DisplayName("Placeholders are substituted")
+    void interpolation(final TestInfo info) {
+        final String pid = info.getTestClass().orElseThrow(IllegalStateException::new).getName() + "." +
+                info.getTestMethod().orElseThrow(IllegalStateException::new).getName() + ".pid";
+        System.setProperty("winegrower.service." + pid + ".value", ">${java.version:-no}<");
+        final Configuration configuration = configurationAdmin.getConfiguration(pid);
+        assertEquals('>' + System.getProperty("java.version", "no") + '<',
+                configuration.getProperties().get("value"));
+    }
+
+    @Test
     @DisplayName("ConfigurationAdmin should be able to use implicitly the environment")
     void envVarOverride(final TestInfo info) {
         final List<ConfigurationListener> listeners = new ArrayList<>();