FELIX-6192 Support default values and type conversion

Support for default values


git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1869603 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/configadmin-plugins/interpolation/src/main/java/org/apache/felix/configadmin/plugin/interpolation/InterpolationConfigurationPlugin.java b/configadmin-plugins/interpolation/src/main/java/org/apache/felix/configadmin/plugin/interpolation/InterpolationConfigurationPlugin.java
index 2a8418f..f9f0184 100644
--- a/configadmin-plugins/interpolation/src/main/java/org/apache/felix/configadmin/plugin/interpolation/InterpolationConfigurationPlugin.java
+++ b/configadmin-plugins/interpolation/src/main/java/org/apache/felix/configadmin/plugin/interpolation/InterpolationConfigurationPlugin.java
@@ -25,8 +25,11 @@
 import java.io.File;
 import java.io.IOException;
 import java.nio.file.Files;
+import java.util.Collections;
 import java.util.Dictionary;
 import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.function.Function;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -83,10 +86,10 @@
                         newVal = replaceVariablesFromProperties(key, sv, pid);
                     }
 
-                    if (newVal != null)
+                    if (newVal != null && !newVal.equals(sv)) {
                         properties.put(key, newVal);
-
-                    getLog().info("Replaced value of configuration property '{}' for PID {}", key, pid);
+                        getLog().info("Replaced value of configuration property '{}' for PID {}", key, pid);
+                    }
                 }
             }
         }
@@ -140,13 +143,44 @@
             final String var = m.group();
 
             final int len = var.length();
-            final String varName = var.substring(prefix.length(), len - SUFFIX.length());
+            final int idx = var.indexOf(';');
+
+            final Map<String, String> directives;
+            final int endIdx;
+            if (idx >= 0) {
+                endIdx = idx;
+                directives = parseDirectives(var.substring(idx, len - SUFFIX.length()));
+            } else {
+                endIdx = len - SUFFIX.length();
+                directives = Collections.emptyMap();
+            }
+
+            final String varName = var.substring(prefix.length(), endIdx);
             String replacement = valueSource.apply(varName);
-            if (replacement != null)
+            if (replacement != null) {
                 m.appendReplacement(sb, Matcher.quoteReplacement(replacement));
+            } else {
+                String defVal = directives.get("default");
+                if (defVal != null) {
+                    m.appendReplacement(sb, Matcher.quoteReplacement(defVal));
+                }
+            }
         }
         m.appendTail(sb);
 
         return sb.toString();
     }
+
+    private Map<String, String> parseDirectives(String dirString) {
+        Map<String, String> dirs = new HashMap<>();
+
+        for (String dir : dirString.split(";")) {
+            String[] kv = dir.split("=");
+            if (kv.length == 2) {
+                dirs.put(kv[0], kv[1]);
+            }
+        }
+
+        return dirs;
+    }
 }
diff --git a/configadmin-plugins/interpolation/src/test/java/org/apache/felix/configadmin/plugin/interpolation/InterpolationConfigurationPluginTest.java b/configadmin-plugins/interpolation/src/test/java/org/apache/felix/configadmin/plugin/interpolation/InterpolationConfigurationPluginTest.java
index dc26dc2..5db01e7 100644
--- a/configadmin-plugins/interpolation/src/test/java/org/apache/felix/configadmin/plugin/interpolation/InterpolationConfigurationPluginTest.java
+++ b/configadmin-plugins/interpolation/src/test/java/org/apache/felix/configadmin/plugin/interpolation/InterpolationConfigurationPluginTest.java
@@ -48,14 +48,16 @@
         Dictionary<String, Object> dict = new Hashtable<>();
         dict.put("foo", "bar");
         dict.put("replaced", "$[secret:testfile]");
+        dict.put("defaulted", "$[secret:not_there;default=defval123]");
         dict.put("cur.user", "$[env:" + userVar + "]");
         dict.put("intval", 999);
         dict.put(Constants.SERVICE_PID, "my.service");
         plugin.modifyConfiguration(null, dict);
 
-        assertEquals(5, dict.size());
+        assertEquals(6, dict.size());
         assertEquals("bar", dict.get("foo"));
         assertEquals("line1\nline2", dict.get("replaced"));
+        assertEquals("defval123", dict.get("defaulted"));
         assertEquals(envUser, dict.get("cur.user"));
         assertEquals("my.service", dict.get(Constants.SERVICE_PID));
         assertEquals(999, dict.get("intval"));
@@ -128,4 +130,16 @@
 
         assertEquals("foo", plugin.replaceVariablesFromFile("akey", "foo", "apid"));
     }
+
+    @Test
+    public void testDefault() throws IOException {
+        InterpolationConfigurationPlugin plugin = new InterpolationConfigurationPlugin(null, null);
+
+        Dictionary<String, Object> dict = new Hashtable<>();
+        dict.put("defaulted", "$[env:notset;default=foo]");
+
+        plugin.modifyConfiguration(null, dict);
+
+        assertEquals("foo", dict.get("defaulted"));
+    }
 }