Repository: deltaspike
Updated Branches:
  refs/heads/master 2abbba651 -> ac3d5829c


DELTASPIKE-1126 variable support for configured values

With this patch it is possible to configure something like
myapp.someapp.soap.endpoint=${someapp.host.url}/random/path
someapp.host.url=http://localhost:8080


Project: http://git-wip-us.apache.org/repos/asf/deltaspike/repo
Commit: http://git-wip-us.apache.org/repos/asf/deltaspike/commit/ac3d5829
Tree: http://git-wip-us.apache.org/repos/asf/deltaspike/tree/ac3d5829
Diff: http://git-wip-us.apache.org/repos/asf/deltaspike/diff/ac3d5829

Branch: refs/heads/master
Commit: ac3d5829c0ccaeffaf23de07d39557a590ec6b91
Parents: 2abbba6
Author: Mark Struberg <[email protected]>
Authored: Mon Apr 11 19:12:43 2016 +0200
Committer: Mark Struberg <[email protected]>
Committed: Mon Apr 11 19:12:43 2016 +0200

----------------------------------------------------------------------
 .../core/api/config/ConfigResolver.java         | 61 ++++++++++++++++++--
 .../test/api/config/ConfigResolverTest.java     | 25 ++++++++
 .../test/api/config/TestConfigSource.java       | 11 ++++
 3 files changed, 93 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ac3d5829/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/config/ConfigResolver.java
----------------------------------------------------------------------
diff --git 
a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/config/ConfigResolver.java
 
b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/config/ConfigResolver.java
index 075b59f..ec5bf1a 100644
--- 
a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/config/ConfigResolver.java
+++ 
b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/config/ConfigResolver.java
@@ -173,6 +173,35 @@ public final class ConfigResolver
         return fallbackToDefaultIfEmpty(key, value, defaultValue);
     }
 
+    public static String getPropertyValue(String key, String defaultValue, 
boolean evaluateVariables)
+    {
+        String value = getPropertyValue(key, defaultValue);
+        if (value != null && evaluateVariables)
+        {
+            int startVar = 0;
+            while ((startVar = value.indexOf("${", startVar)) >= 0)
+            {
+                int endVar = value.indexOf("}", startVar);
+                if (endVar <= 0)
+                {
+                    break;
+                }
+                String variable = value.substring(startVar + 2, endVar);
+                if (variable.isEmpty())
+                {
+                    break;
+                }
+                String variableValue = getPropertyValue(variable, null, true);
+                if (variableValue != null)
+                {
+                    value = value.replace("${" + variable + "}", 
variableValue);
+                }
+                startVar++;
+            }
+        }
+        return value;
+    }
+
     /**
      * Resolves the value configured for the given key.
      *
@@ -606,6 +635,21 @@ public final class ConfigResolver
         TypedResolver<T> cacheFor(TimeUnit timeUnit, long value);
 
         /**
+         * Whether to evaluate variables in configured values.
+         * A variable starts with '${' and ends with '}', e.g.
+         * <pre>
+         * mycompany.some.url=${myserver.host}/some/path
+         * myserver.host=http://localhost:8081
+         * </pre>
+         * If 'evaluateVariables' is enabled, the result for the above key
+         * {@code "mycompany.some.url"} would be:
+         * {@code "http://localhost:8081/some/path"}
+         * @param evaluateVariables whether to evaluate variables in values or 
not
+         * @return This builder
+         */
+        TypedResolver<T> evaluateVariables(boolean evaluateVariables);
+
+        /**
          * Returns the converted resolved filtered value.
          * @return the resolved value
          */
@@ -704,6 +748,8 @@ public final class ConfigResolver
 
         private Converter<?> converter;
 
+        private boolean evaluateVariables = false;
+
         private long cacheTimeMs = -1;
         private volatile long reloadAfter = -1;
         private T lastValue = null;
@@ -799,6 +845,13 @@ public final class ConfigResolver
         }
 
         @Override
+        public TypedResolver<T> evaluateVariables(boolean evaluateVariables)
+        {
+            this.evaluateVariables = evaluateVariables;
+            return this;
+        }
+
+        @Override
         public T getValue()
         {
             if (cacheTimeMs > 0)
@@ -875,7 +928,7 @@ public final class ConfigResolver
             }
 
             // make initial resolution of longest key
-            value = getPropertyValue(keyResolved);
+            value = getPropertyValue(keyResolved, null, evaluateVariables);
 
             // try fallbacks if not strictly
             if (value == null && !strictly)
@@ -889,7 +942,7 @@ public final class ConfigResolver
                     case 2:
                         // try base.param
                         keyResolved = keyOriginal + "." + parameterValue;
-                        value = getPropertyValue(keyResolved);
+                        value = getPropertyValue(keyResolved, null, 
evaluateVariables);
 
                         if (value != null)
                         {
@@ -899,7 +952,7 @@ public final class ConfigResolver
                         // try base.ps
                         ps = getProjectStage();
                         keyResolved = keyOriginal + "." + ps;
-                        value = getPropertyValue(keyResolved);
+                        value = getPropertyValue(keyResolved, null, 
evaluateVariables);
 
                         if (value != null)
                         {
@@ -909,7 +962,7 @@ public final class ConfigResolver
                     case 1:
                         // try base
                         keyResolved = keyOriginal;
-                        value = getPropertyValue(keyResolved);
+                        value = getPropertyValue(keyResolved, null, 
evaluateVariables);
                         return value;
 
                     default:

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ac3d5829/deltaspike/core/api/src/test/java/org/apache/deltaspike/test/api/config/ConfigResolverTest.java
----------------------------------------------------------------------
diff --git 
a/deltaspike/core/api/src/test/java/org/apache/deltaspike/test/api/config/ConfigResolverTest.java
 
b/deltaspike/core/api/src/test/java/org/apache/deltaspike/test/api/config/ConfigResolverTest.java
index cc5951f..bfac665 100644
--- 
a/deltaspike/core/api/src/test/java/org/apache/deltaspike/test/api/config/ConfigResolverTest.java
+++ 
b/deltaspike/core/api/src/test/java/org/apache/deltaspike/test/api/config/ConfigResolverTest.java
@@ -27,6 +27,7 @@ import org.junit.Before;
 import org.junit.Test;
 
 import java.util.List;
+import java.util.concurrent.TimeUnit;
 
 public class ConfigResolverTest
 {
@@ -134,6 +135,30 @@ public class ConfigResolverTest
 
     }
 
+    @Test
+    public void testConfigVariableReplacement()
+    {
+        String url = 
ConfigResolver.getPropertyValue("deltaspike.test.someapp.soap.endpoint", "", 
true);
+        Assert.assertEquals("http://localhost:12345/someservice/myendpoint";, 
url);
+    }
+
+    @Test
+    public void testConfigVariableNotExisting()
+    {
+        String url = 
ConfigResolver.getPropertyValue("deltaspike.test.nonexisting.variable", "", 
true);
+        Assert.assertEquals("${does.not.exist}/someservice/myendpoint", url);
+
+    }
+    @Test
+    public void testConfigVariableRecursiveDeclaration()
+    {
+        String url = 
ConfigResolver.getPropertyValue("deltaspike.test.recursive.variable1", "", 
true);
+        Assert.assertEquals("pre-crazy-post/ohgosh/crazy", url);
+
+        ConfigResolver.TypedResolver<String> tr = 
ConfigResolver.resolve("deltaspike.test.recursive.variable1").evaluateVariables(true);
+        Assert.assertEquals("pre-crazy-post/ohgosh/crazy", tr.getValue());
+    }
+
     public static class TestConfigFilter implements ConfigFilter
     {
         @Override

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ac3d5829/deltaspike/core/api/src/test/java/org/apache/deltaspike/test/api/config/TestConfigSource.java
----------------------------------------------------------------------
diff --git 
a/deltaspike/core/api/src/test/java/org/apache/deltaspike/test/api/config/TestConfigSource.java
 
b/deltaspike/core/api/src/test/java/org/apache/deltaspike/test/api/config/TestConfigSource.java
index 709c1ee..c0f34c7 100644
--- 
a/deltaspike/core/api/src/test/java/org/apache/deltaspike/test/api/config/TestConfigSource.java
+++ 
b/deltaspike/core/api/src/test/java/org/apache/deltaspike/test/api/config/TestConfigSource.java
@@ -78,6 +78,17 @@ public class TestConfigSource implements ConfigSource
         props.put("deltaspike.test.date-value", "2014-12-24");
         props.put("deltaspike.test.invalid-value", "wrong");
         
props.put("org.apache.deltaspike.core.spi.activation.ClassDeactivator","org.apache.deltaspike.core.util.activation.EditableTestDeactivator");
+
+        // test for variable replacement
+        props.put("deltaspike.test.host.url", "http://localhost:12345";);
+        props.put("deltaspike.test.someapp.soap.endpoint", 
"${deltaspike.test.host.url}/someservice/myendpoint");
+
+        props.put("deltaspike.test.nonexisting.variable", 
"${does.not.exist}/someservice/myendpoint");
+
+        props.put("deltaspike.test.recursive.variable1", 
"${deltaspike.test.recursive.variable2}/ohgosh/${deltaspike.test.recursive.variable3}");
+        props.put("deltaspike.test.recursive.variable2", 
"pre-${deltaspike.test.recursive.variable3}-post");
+        props.put("deltaspike.test.recursive.variable3", "crazy");
+
     }
 
     @Override

Reply via email to