FELIX-2433 allow "$(...)" expansion


git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@956567 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Tokenizer.java b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Tokenizer.java
index 25a7299..0856bf0 100644
--- a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Tokenizer.java
+++ b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Tokenizer.java
@@ -18,7 +18,6 @@
  */
 package org.apache.felix.gogo.runtime;
 
-
 /**
  * Bash-like tokenizer.
  * 
@@ -469,14 +468,14 @@
      * expand variables, quotes and escapes in word.
      * @param vars
      * @return
+     * @throws Exception 
      */
-    public static Object expand(CharSequence word, Evaluate eval)
+    public static Object expand(CharSequence word, Evaluate eval) throws Exception
     {
         return expand(word, eval, false);
     }
 
-    private static Object expand(CharSequence word, Evaluate eval,
-        boolean inQuote)
+    private static Object expand(CharSequence word, Evaluate eval, boolean inQuote) throws Exception
     {
         final String special = "$\\\"'";
         int i = word.length();
@@ -492,7 +491,7 @@
         return new Tokenizer(word, eval, inQuote).expand();
     }
 
-    public Object expand(CharSequence word, short line, short column)
+    public Object expand(CharSequence word, short line, short column) throws Exception
     {
         return expand(new Token(Type.WORD, word, line, column), evaluate, inQuote);
     }
@@ -502,7 +501,7 @@
         return new Token(Type.WORD, value, line, column);
     }
 
-    private Object expand()
+    private Object expand() throws Exception
     {
         StringBuilder buf = new StringBuilder();
 
@@ -581,27 +580,37 @@
         return buf.toString();
     }
 
-    private Object expandVar()
+    private Object expandVar() throws Exception
     {
         assert '$' == ch;
         Object val;
 
         if (getch() != '{')
         {
-            int start = index - 1;
-            while (isName(ch))
-            {
+            if ('(' == ch)
+            { // support $(...) FELIX-2433
+                short sLine = line;
+                short sCol = column;
+                val = evaluate.eval(new Token(Type.EXECUTION, group(), sLine, sCol));
                 getch();
             }
-
-            if (index - 1 == start)
-            {
-                val = "$";
-            }
             else
             {
-                String name = text.subSequence(start, index - 1).toString();
-                val = evaluate.get(name);
+                int start = index - 1;
+                while (isName(ch))
+                {
+                    getch();
+                }
+
+                if (index - 1 == start)
+                {
+                    val = "$";
+                }
+                else
+                {
+                    String name = text.subSequence(start, index - 1).toString();
+                    val = evaluate.get(name);
+                }
             }
         }
         else
diff --git a/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/TestParser2.java b/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/TestParser2.java
index a21e0a1..485c988 100644
--- a/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/TestParser2.java
+++ b/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/TestParser2.java
@@ -59,11 +59,18 @@
     {
         Context c = new Context();
         c.addCommand("echo", this);
-
         // FELIX-2432
         assertEquals("null x", c.execute("echo $expandsToNull x"));
     }
 
+    public void testStringExecution() throws Exception
+    {
+        Context c = new Context();
+        c.addCommand("echo", this);
+        // FELIX-2433
+        assertEquals("helloworld", c.execute("echo \"$(echo hello)world\""));
+    }
+
     public CharSequence echo(Object args[])
     {
         if (args == null)