felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From db...@apache.org
Subject svn commit: r959276 - in /felix/trunk/gogo/runtime/src: main/java/org/apache/felix/gogo/runtime/ test/java/org/apache/felix/gogo/runtime/
Date Wed, 30 Jun 2010 12:03:03 GMT
Author: dbaum
Date: Wed Jun 30 12:03:02 2010
New Revision: 959276

URL: http://svn.apache.org/viewvc?rev=959276&view=rev
Log:
(FELIX-1473) use alternative implementation for method calls on Strings

Modified:
    felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Closure.java
    felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/CommandProcessorImpl.java
    felix/trunk/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/TestParser.java
    felix/trunk/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/TestParser2.java

Modified: felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Closure.java
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Closure.java?rev=959276&r1=959275&r2=959276&view=diff
==============================================================================
--- felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Closure.java (original)
+++ felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Closure.java Wed
Jun 30 12:03:02 2010
@@ -222,6 +222,28 @@ public class Closure implements Function
         return last == null ? null : last.result;
     }
 
+    private Object eval(Object v)
+    {
+        String s = v.toString();
+        if ("null".equals(s))
+        {
+            v = null;
+        }
+        else if ("false".equals(s))
+        {
+            v = false;
+        }
+        else if ("true".equals(s))
+        {
+            v = true;
+        }
+        else
+        {
+            v = s;
+        }
+        return v;
+    }
+
     public Object eval(final Token t) throws Exception
     {
         Object v = null;
@@ -230,26 +252,10 @@ public class Closure implements Function
         {
             case WORD:
                 v = Tokenizer.expand(t, this);
-                
+
                 if (t == v)
                 {
-                    String s = v.toString();
-                    if ("null".equals(s))
-                    {
-                        v = null;
-                    }
-                    else if ("false".equals(s))
-                    {
-                        v = false;
-                    }
-                    else if ("true".equals(s))
-                    {
-                        v = true;
-                    }
-                    else
-                    {
-                        v = s;
-                    }
+                    v = eval(v);
                 }
                 else if (v instanceof CharSequence)
                 {
@@ -280,18 +286,30 @@ public class Closure implements Function
         return v;
     }
 
+    /*
+     * executeStatement handles the following cases:
+     *    <string> '=' word // simple assignment
+     *    <string> '=' word word.. // complex assignment
+     *    <bareword> word.. // command invocation
+     *    <object> // value of <object>
+     *    <object> word.. // method call
+     */
     public Object executeStatement(List<Token> statement) throws Exception
     {
-        // add set -x facility if echo is set
-        if (Boolean.TRUE.equals(session.get("echo")))
+        Object echo = session.get("echo");
+        String xtrace = null;
+        
+        if (echo != null && !"false".equals(echo.toString()))
         {
+            // set -x execution trace
             StringBuilder buf = new StringBuilder("+");
             for (Token token : statement)
             {
                 buf.append(' ');
                 buf.append(token.source());
             }
-            session.err.println(buf);
+            xtrace = buf.toString();
+            session.err.println(xtrace);
         }
 
         List<Object> values = new ArrayList<Object>();
@@ -332,138 +350,167 @@ public class Closure implements Function
             throw new RuntimeException("Command name evaluates to null: " + errTok);
         }
 
-        return execute(cmd, values);
-    }
-
-    private Object execute(Object cmd, List<Object> values) throws Exception
-    {
-        // Now there are the following cases
-        // <string> '=' statement // complex assignment
-        // <string> statement // cmd call
-        // <object> // value of <object>
-        // <object> statement // method call
-
-        boolean dot = values.size() > 1 && ".".equals(String.valueOf(values.get(0)));
-
-        if (cmd instanceof CharSequence && !dot)
+        if (cmd instanceof CharSequence && values.size() > 0
+            && Type.ASSIGN.equals(values.get(0)))
         {
+            values.remove(0);
             String scmd = cmd.toString();
+            Object value;
 
-            if (values.size() > 0 && Type.ASSIGN.equals(values.get(0)))
+            if (values.size() == 0)
             {
-                Object value;
+                return session.variables.remove(scmd);
+            }
 
-                if (values.size() == 1)
+            if (values.size() == 1)
+            {
+                value = values.get(0);
+            }
+            else
+            {
+                cmd = values.remove(0);
+                if (null == cmd)
                 {
-                    return session.variables.remove(scmd);
+                    throw new RuntimeException("Command name evaluates to null: "
+                        + errTok2);
                 }
 
-                if (values.size() == 2)
-                {
-                    value = values.get(1);
-                }
-                else
-                {
-                    cmd = values.get(1);
-                    if (null == cmd)
-                    {
-                        throw new RuntimeException("Command name evaluates to null: "
-                            + errTok2);
-                    }
-                    value = execute(cmd, values.subList(2, values.size()));
-                }
+                trace2(xtrace, cmd, values);
 
-                return assignment(scmd, value);
+                value = bareword(statement.get(2)) ? executeCmd(cmd.toString(), values)
+                    : executeMethod(cmd, values);
             }
-            else
-            {
-                String scopedFunction = scmd;
-                Object x = get(scmd);
 
-                if (!(x instanceof Function))
-                {
-                    if (scmd.indexOf(':') < 0)
-                    {
-                        scopedFunction = "*:" + scmd;
-                    }
+            return assignment(scmd, value);
+        }
 
-                    x = get(scopedFunction);
+        trace2(xtrace, cmd, values);
 
-                    if (x == null || !(x instanceof Function))
-                    {
-                        // try default command handler
-                        if (session.get(DEFAULT_LOCK) == null)
-                        {
-                            x = get("default");
-                            if (x == null)
-                            {
-                                x = get("*:default");
-                            }
-
-                            if (x instanceof Function)
-                            {
-                                try
-                                {
-                                    session.put(DEFAULT_LOCK, true);
-                                    values.add(0, scmd);
-                                    return ((Function) x).execute(session, values);
-                                }
-                                finally
-                                {
-                                    session.variables.remove(DEFAULT_LOCK);
-                                }
-                            }
-                        }
+        return bareword(statement.get(0)) ? executeCmd(cmd.toString(), values)
+            : executeMethod(cmd, values);
+    }
 
-                        throw new IllegalArgumentException("Command not found: " + scmd);
-                    }
-                }
-                return ((Function) x).execute(session, values);
+    // second level expanded execution trace
+    private void trace2(String trace1, Object cmd, List<Object> values)
+    {
+        if ("verbose".equals(session.get("echo")))
+        {
+            StringBuilder buf = new StringBuilder("+ " + cmd);
+
+            for (Object value : values)
+            {
+                buf.append(' ');
+                buf.append(value);
+            }
+
+            String trace2 = buf.toString();
+
+            if (!trace2.equals(trace1))
+            {
+                session.err.println("+" + trace2);
             }
         }
-        else
+    }
+
+    private boolean bareword(Token t) throws Exception
+    {
+        return ((t.type == Type.WORD) && (t == Tokenizer.expand(t, this)) &&
(eval((Object) t) instanceof String));
+    }
+
+    private Object executeCmd(String scmd, List<Object> values) throws Exception
+    {
+        String scopedFunction = scmd;
+        Object x = get(scmd);
+
+        if (!(x instanceof Function))
         {
-            if (values.isEmpty())
+            if (scmd.indexOf(':') < 0)
             {
-                return cmd;
+                scopedFunction = "*:" + scmd;
             }
-            else if (dot)
-            {
-                // FELIX-1473 - allow methods calls on String objects
-                Object target = cmd;
-                ArrayList<Object> args = new ArrayList<Object>();
-                values.remove(0);
 
-                for (Object arg : values)
+            x = get(scopedFunction);
+
+            if (x == null || !(x instanceof Function))
+            {
+                // try default command handler
+                if (session.get(DEFAULT_LOCK) == null)
                 {
-                    if (".".equals(arg))
+                    x = get("default");
+                    if (x == null)
                     {
-                        target = Reflective.method(session, target, args.remove(0).toString(),
args);
-                        args.clear();
+                        x = get("*:default");
                     }
-                    else
+
+                    if (x instanceof Function)
                     {
-                        args.add(arg);
+                        try
+                        {
+                            session.put(DEFAULT_LOCK, true);
+                            values.add(0, scmd);
+                            return ((Function) x).execute(session, values);
+                        }
+                        finally
+                        {
+                            session.variables.remove(DEFAULT_LOCK);
+                        }
                     }
                 }
 
-                if (args.size() == 0)
+                throw new IllegalArgumentException("Command not found: " + scmd);
+            }
+        }
+        return ((Function) x).execute(session, values);
+    }
+
+    private Object executeMethod(Object cmd, List<Object> values) throws Exception
+    {
+        if (values.isEmpty())
+        {
+            return cmd;
+        }
+
+        boolean dot = values.size() > 1 && ".".equals(String.valueOf(values.get(0)));
+
+        // FELIX-1473 - allow method chaining using dot pseudo-operator, e.g.
+        //  (bundle 0) . loadClass java.net.InetAddress . localhost . hostname
+        //  (((bundle 0) loadClass java.net.InetAddress ) localhost ) hostname
+        if (dot)
+        {
+            Object target = cmd;
+            ArrayList<Object> args = new ArrayList<Object>();
+            values.remove(0);
+
+            for (Object arg : values)
+            {
+                if (".".equals(arg))
+                {
+                    target = Reflective.method(session, target,
+                        args.remove(0).toString(), args);
+                    args.clear();
+                }
+                else
                 {
-                    return target;
+                    args.add(arg);
                 }
-
-                return Reflective.method(session, target, args.remove(0).toString(), args);
-            }
-            else if (cmd.getClass().isArray() && values.size() == 1)
-            {
-                Object[] cmdv = (Object[])cmd;
-                String index = values.get(0).toString();
-                return "length".equals(index) ? cmdv.length : cmdv[Integer.parseInt(index)];
             }
-            else
+
+            if (args.size() == 0)
             {
-                return Reflective.method(session, cmd, values.remove(0).toString(), values);
+                return target;
             }
+
+            return Reflective.method(session, target, args.remove(0).toString(), args);
+        }
+        else if (cmd.getClass().isArray() && values.size() == 1)
+        {
+            Object[] cmdv = (Object[]) cmd;
+            String index = values.get(0).toString();
+            return "length".equals(index) ? cmdv.length : cmdv[Integer.parseInt(index)];
+        }
+        else
+        {
+            return Reflective.method(session, cmd, values.remove(0).toString(), values);
         }
     }
 
@@ -487,7 +534,7 @@ public class Closure implements Function
                 Object oval = eval(t);
                 if (oval.getClass().isArray())
                 {
-                    for (Object o : (Object[])oval)
+                    for (Object o : (Object[]) oval)
                     {
                         olist.add(o);
                     }

Modified: felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/CommandProcessorImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/CommandProcessorImpl.java?rev=959276&r1=959275&r2=959276&view=diff
==============================================================================
--- felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/CommandProcessorImpl.java
(original)
+++ felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/CommandProcessorImpl.java
Wed Jun 30 12:03:02 2010
@@ -49,6 +49,7 @@ public class CommandProcessorImpl implem
         this.context = context;
         addCommand("osgi", this, "addCommand");
         addCommand("osgi", this, "removeCommand");
+        addCommand("osgi", this, "eval");
     }
 
     public CommandSession createSession(InputStream in, PrintStream out, PrintStream err)
@@ -65,12 +66,12 @@ public class CommandProcessorImpl implem
     {
         converters.remove(c);
     }
-    
+
     public Set<String> getCommands()
     {
         return commands.keySet();
     }
-    
+
     BundleContext getContext()
     {
         return context;
@@ -84,16 +85,16 @@ public class CommandProcessorImpl implem
         {
             return null;
         }
-        
+
         name = name.toLowerCase();
         Object cmd = commands.get(name);
         String cfunction = name.substring(colon);
         boolean anyScope = (colon == 1 && name.charAt(0) == '*');
-        
+
         if (null == cmd && anyScope)
         {
             String scopePath = (null == path ? "*" : path.toString());
-            
+
             for (String scope : scopePath.split(":"))
             {
                 if (scope.equals("*"))
@@ -111,7 +112,7 @@ public class CommandProcessorImpl implem
                 {
                     cmd = commands.get(scope + cfunction);
                 }
-                
+
                 if (cmd != null)
                 {
                     break;
@@ -220,4 +221,19 @@ public class CommandProcessorImpl implem
         }
         return null;
     }
+
+    // eval is needed to force expansions to be treated as commands (FELIX-1473)
+    public Object eval(CommandSession session, Object[] argv) throws Exception
+    {
+        StringBuilder buf = new StringBuilder();
+
+        for (Object arg : argv)
+        {
+            if (buf.length() > 0)
+                buf.append(' ');
+            buf.append(arg);
+        }
+
+        return session.execute(buf);
+    }
 }

Modified: felix/trunk/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/TestParser.java
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/TestParser.java?rev=959276&r1=959275&r2=959276&view=diff
==============================================================================
--- felix/trunk/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/TestParser.java (original)
+++ felix/trunk/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/TestParser.java Wed
Jun 30 12:03:02 2010
@@ -154,7 +154,7 @@ public class TestParser extends TestCase
 
         assertEquals("a", c.execute("e = { echo $1 } ; e a   b"));
         assertEquals("b", c.execute("e = { echo $2 } ; e a   b"));
-        assertEquals("b", c.execute("e = { $args } ; e echo  b"));
+        assertEquals("b", c.execute("e = { eval $args } ; e echo  b"));
         assertEquals("ca b", c.execute("e = { echo c$args } ; e a  b"));
         assertEquals("c a b", c.execute("e = { echo c $args } ; e a  b"));
         assertEquals("ca  b", c.execute("e = { echo c$args } ; e 'a  b'"));
@@ -233,8 +233,8 @@ public class TestParser extends TestCase
         Context c = new Context();
         c.addCommand("echo", this);
         assertEquals("a", c.execute("echo a") + "");
-        assertEquals("a", c.execute("(echo echo) a") + "");
-        assertEquals("a", c.execute("((echo echo) echo) (echo a)") + "");
+        assertEquals("a", c.execute("eval (echo echo) a") + "");
+        //assertEquals("a", c.execute("((echo echo) echo) (echo a)") + "");
         assertEquals("3", c.execute("[a=2 (echo b)=(echo 3)] get b").toString());
     }
 

Modified: felix/trunk/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/TestParser2.java
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/TestParser2.java?rev=959276&r1=959275&r2=959276&view=diff
==============================================================================
--- felix/trunk/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/TestParser2.java
(original)
+++ felix/trunk/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/TestParser2.java
Wed Jun 30 12:03:02 2010
@@ -69,6 +69,15 @@ public class TestParser2 extends TestCas
         c.addCommand("echo", this);
         // FELIX-2433
         assertEquals("helloworld", c.execute("echo \"$(echo hello)world\""));
+        
+         // FELIX-1473 - allow method calls on String objects
+        assertEquals("hello", c.execute("cmd = echo; eval $cmd hello"));
+        assertEquals(4, c.execute("'four' length"));
+        try {
+            c.execute("four length");
+            fail("expected: command not found: four");
+        } catch (IllegalArgumentException e) {
+        }
     }
 
     public CharSequence echo(Object args[])



Mime
View raw message