You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ja...@apache.org on 2015/01/19 20:10:25 UTC

svn commit: r1653078 - in /felix/trunk/gogo: command/src/main/java/org/apache/felix/gogo/command/ runtime/ runtime/src/main/java/org/apache/felix/gogo/runtime/ runtime/src/main/java/org/apache/felix/gogo/runtime/activator/ runtime/src/main/java/org/apa...

Author: jawi
Date: Mon Jan 19 19:10:24 2015
New Revision: 1653078

URL: http://svn.apache.org/r1653078
Log:
FELIX-4679 - Revert patch for FELIX-4671:

- revert patch for expression support as the parser couldn't cope
  with the double parenthesises properly for non-expressions.


Removed:
    felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Expression.java
    felix/trunk/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/TestParser3.java
    felix/trunk/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/expr/ExpressionTest.java
Modified:
    felix/trunk/gogo/command/src/main/java/org/apache/felix/gogo/command/Inspect.java
    felix/trunk/gogo/runtime/NOTICE
    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/main/java/org/apache/felix/gogo/runtime/CommandSessionImpl.java
    felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Parser.java
    felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Tokenizer.java
    felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/activator/Activator.java
    felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/activator/EventAdminListener.java
    felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/threadio/ThreadPrintStream.java
    felix/trunk/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/Context.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/TestTokenizer.java
    felix/trunk/gogo/shell/src/main/java/org/apache/felix/gogo/shell/Activator.java

Modified: felix/trunk/gogo/command/src/main/java/org/apache/felix/gogo/command/Inspect.java
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/command/src/main/java/org/apache/felix/gogo/command/Inspect.java?rev=1653078&r1=1653077&r2=1653078&view=diff
==============================================================================
--- felix/trunk/gogo/command/src/main/java/org/apache/felix/gogo/command/Inspect.java (original)
+++ felix/trunk/gogo/command/src/main/java/org/apache/felix/gogo/command/Inspect.java Mon Jan 19 19:10:24 2015
@@ -21,8 +21,8 @@ package org.apache.felix.gogo.command;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
-
 import java.util.Map;
+
 import org.apache.felix.service.command.Descriptor;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
@@ -32,9 +32,6 @@ import org.osgi.framework.wiring.BundleC
 import org.osgi.framework.wiring.BundleRequirement;
 import org.osgi.framework.wiring.BundleWire;
 import org.osgi.framework.wiring.BundleWiring;
-import org.osgi.service.packageadmin.ExportedPackage;
-import org.osgi.service.packageadmin.PackageAdmin;
-import org.osgi.service.packageadmin.RequiredBundle;
 
 public class Inspect
 {

Modified: felix/trunk/gogo/runtime/NOTICE
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/runtime/NOTICE?rev=1653078&r1=1653077&r2=1653078&view=diff
==============================================================================
--- felix/trunk/gogo/runtime/NOTICE (original)
+++ felix/trunk/gogo/runtime/NOTICE Mon Jan 19 19:10:24 2015
@@ -4,7 +4,3 @@ Copyright 2014 The Apache Software Found
 This product includes software developed at
 The Apache Software Foundation (http://www.apache.org/).
 Licensed under the Apache License 2.0.
-
-This product includes software developped by
-Udo Klimaschewski (http://UdoJava.com/).
-Licensed under the MIT License.

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=1653078&r1=1653077&r2=1653078&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 Mon Jan 19 19:10:24 2015
@@ -19,7 +19,11 @@
 package org.apache.felix.gogo.runtime;
 
 import java.io.EOFException;
-import java.util.*;
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.Map.Entry;
 
 import org.apache.felix.gogo.runtime.Tokenizer.Type;
@@ -31,7 +35,6 @@ public class Closure implements Function
     public static final String LOCATION = ".location";
     private static final String DEFAULT_LOCK = ".defaultLock";
 
-    private static final long serialVersionUID = 1L;
     private static final ThreadLocal<String> location = new ThreadLocal<String>();
 
     private final CommandSessionImpl session;
@@ -289,10 +292,6 @@ public class Closure implements Function
                 v = t.type;
                 break;
 
-            case EXPR:
-                v = expr(t.value);
-                break;
-
             default:
                 throw new SyntaxError(t.line, t.column, "unexpected token: " + t.type);
         }
@@ -534,11 +533,6 @@ public class Closure implements Function
         return value;
     }
 
-    private Object expr(CharSequence expr) throws Exception
-    {
-        return session.expr(expr);
-    }
-
     private Object array(Token array) throws Exception
     {
         List<Token> list = new ArrayList<Token>();

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=1653078&r1=1653077&r2=1653078&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 Mon Jan 19 19:10:24 2015
@@ -21,16 +21,11 @@ package org.apache.felix.gogo.runtime;
 import java.io.InputStream;
 import java.io.PrintStream;
 import java.lang.reflect.Method;
-import java.math.BigDecimal;
 import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
-import java.util.SortedMap;
 import java.util.TreeSet;
 import java.util.WeakHashMap;
 import java.util.concurrent.ConcurrentHashMap;
@@ -63,7 +58,8 @@ public class CommandProcessorImpl implem
     {
         synchronized (sessions)
         {
-            if (stopped) {
+            if (stopped)
+            {
                 throw new IllegalStateException("CommandProcessor has been stopped");
             }
             CommandSessionImpl session = new CommandSessionImpl(this, in, out, err);
@@ -72,6 +68,17 @@ public class CommandProcessorImpl implem
         }
     }
 
+    void closeSession(CommandSessionImpl session)
+    {
+        synchronized (sessions)
+        {
+            if (sessions.remove(session) != null)
+            {
+                System.out.println("CLOSED: " + session);
+            }
+        }
+    }
+
     public void stop()
     {
         synchronized (sessions)
@@ -173,8 +180,7 @@ public class CommandProcessorImpl implem
 
     public void addCommand(String scope, Object target)
     {
-        Class<?> tc = (target instanceof Class<?>) ? (Class<?>) target
-            : target.getClass();
+        Class<?> tc = (target instanceof Class<?>) ? (Class<?>) target : target.getClass();
         addCommand(scope, target, tc);
     }
 
@@ -326,8 +332,7 @@ public class CommandProcessorImpl implem
         }
     }
 
-    void afterExecute(CommandSession session, CharSequence commandline,
-        Exception exception)
+    void afterExecute(CommandSession session, CharSequence commandline, Exception exception)
     {
         for (CommandSessionListener l : listeners)
         {
@@ -356,8 +361,4 @@ public class CommandProcessorImpl implem
             }
         }
     }
-
-    public Object expr(CommandSessionImpl session, CharSequence expr) {
-        return new Expression(expr.toString()).eval(session.variables);
-    }
 }

Modified: felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/CommandSessionImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/CommandSessionImpl.java?rev=1653078&r1=1653077&r2=1653078&view=diff
==============================================================================
--- felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/CommandSessionImpl.java (original)
+++ felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/CommandSessionImpl.java Mon Jan 19 19:10:24 2015
@@ -32,9 +32,7 @@ import java.util.Dictionary;
 import java.util.Enumeration;
 import java.util.Formatter;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
 
 import org.apache.felix.service.command.CommandSession;
 import org.apache.felix.service.command.Converter;
@@ -47,14 +45,14 @@ public class CommandSessionImpl implemen
     public static final String VARIABLES = ".variables";
     public static final String COMMANDS = ".commands";
     private static final String COLUMN = "%-20s %s\n";
-    
+
     protected InputStream in;
     protected PrintStream out;
     PrintStream err;
-    
+
     private final CommandProcessorImpl processor;
     protected final Map<String, Object> variables = new HashMap<String, Object>();
-    private boolean closed;
+    private volatile boolean closed;
 
     protected CommandSessionImpl(CommandProcessorImpl shell, InputStream in, PrintStream out, PrintStream err)
     {
@@ -63,7 +61,7 @@ public class CommandSessionImpl implemen
         this.out = out;
         this.err = err;
     }
-    
+
     ThreadIO threadIO()
     {
         return processor.threadIO;
@@ -71,7 +69,12 @@ public class CommandSessionImpl implemen
 
     public void close()
     {
-        this.closed = true;
+        if (!this.closed)
+        {
+            System.out.println("CLOSING SESSION!");
+            this.processor.closeSession(this);
+            this.closed = true;
+        }
     }
 
     public Object execute(CharSequence commandline) throws Exception
@@ -119,7 +122,7 @@ public class CommandSessionImpl implemen
         }
 
         Object val = processor.constants.get(name);
-        if( val != null )
+        if (val != null)
         {
             return val;
         }
@@ -137,13 +140,13 @@ public class CommandSessionImpl implemen
             }
             return val;
         }
-        else if( val != null )
+        else if (val != null)
         {
             return val;
         }
 
         val = variables.get(name);
-        if( val != null )
+        if (val != null)
         {
             return val;
         }
@@ -165,8 +168,7 @@ public class CommandSessionImpl implemen
     }
 
     @SuppressWarnings("unchecked")
-    public CharSequence format(Object target, int level, Converter escape)
-        throws Exception
+    public CharSequence format(Object target, int level, Converter escape) throws Exception
     {
         if (target == null)
         {
@@ -349,9 +351,7 @@ public class CommandSessionImpl implemen
             try
             {
                 String name = m.getName();
-                if (m.getName().startsWith("get") && !m.getName().equals("getClass")
-                    && m.getParameterTypes().length == 0
-                    && Modifier.isPublic(m.getModifiers()))
+                if (m.getName().startsWith("get") && !m.getName().equals("getClass") && m.getParameterTypes().length == 0 && Modifier.isPublic(m.getModifiers()))
                 {
                     found = true;
                     name = name.substring(3);
@@ -396,9 +396,4 @@ public class CommandSessionImpl implemen
         }
     }
 
-    public Object expr(CharSequence expr)
-    {
-        return processor.expr(this, expr);
-    }
-
 }

Modified: felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Parser.java
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Parser.java?rev=1653078&r1=1653077&r2=1653078&view=diff
==============================================================================
--- felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Parser.java (original)
+++ felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Parser.java Mon Jan 19 19:10:24 2015
@@ -97,7 +97,6 @@ public class Parser
                 case EXECUTION:
                 case ARRAY:
                 case ASSIGN:
-                case EXPR:
                     break;
                     
                 default:

Modified: felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Tokenizer.java
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Tokenizer.java?rev=1653078&r1=1653077&r2=1653078&view=diff
==============================================================================
--- felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Tokenizer.java (original)
+++ felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Tokenizer.java Mon Jan 19 19:10:24 2015
@@ -46,7 +46,7 @@ public class Tokenizer
 {
     public enum Type
     {
-        ASSIGN('='), PIPE('|'), SEMICOLON(';'), NEWLINE, ARRAY, CLOSURE, EXPR, EXECUTION, WORD, EOT;
+        ASSIGN('='), PIPE('|'), SEMICOLON(';'), NEWLINE, ARRAY, CLOSURE, EXECUTION, WORD, EOT;
 
         private char c;
 
@@ -265,43 +265,25 @@ public class Tokenizer
     private CharSequence group()
     {
         final char push = ch;
-        final char push2;
         final char pop;
-        final char pop2;
 
         switch (ch)
         {
             case '{':
                 type = Type.CLOSURE;
-                push2 = 0;
                 pop = '}';
-                pop2 = 0;
                 break;
             case '(':
-                if (peek() == '(') {
-                    getch();
-                    push2 = '(';
-                    type = Type.EXPR;
-                    pop = ')';
-                    pop2 = ')';
-                } else {
-                    type = Type.EXECUTION;
-                    push2 = 0;
-                    pop = ')';
-                    pop2 = 0;
-                }
+                type = Type.EXECUTION;
+                pop = ')';
                 break;
             case '[':
                 type = Type.ARRAY;
-                push2 = 0;
                 pop = ']';
-                pop2 = 0;
                 break;
             default:
                 assert false;
-                push2 = 0;
                 pop = 0;
-                pop2 = 0;
         }
 
         short sLine = line;
@@ -345,17 +327,10 @@ public class Tokenizer
                     break;
 
                 default:
-                    if (push == ch) {
+                    if (push == ch)
                         depth++;
-                    }
-                    else if (pop == ch && --depth == 0) {
-                        if (pop2 == 0)
-                            return text.subSequence(start, index - 1);
-                        else if (pop2 == peek()) {
-                            getch();
-                            return text.subSequence(start, index - 2);
-                        }
-                    }
+                    else if (pop == ch && --depth == 0)
+                        return text.subSequence(start, index - 1);
             }
         }
 
@@ -614,20 +589,11 @@ public class Tokenizer
         if (getch() != '{')
         {
             if ('(' == ch)
-            {
+            { // support $(...) FELIX-2433
                 short sLine = line;
                 short sCol = column;
-                if ('(' == peek())
-                {
-                    val = evaluate.eval(new Token(Type.EXPR, group(), sLine, sCol));
-                    getch();
-                }
-                else
-                {
-                    // support $(...) FELIX-2433
-                    val = evaluate.eval(new Token(Type.EXECUTION, group(), sLine, sCol));
-                    getch();
-                }
+                val = evaluate.eval(new Token(Type.EXECUTION, group(), sLine, sCol));
+                getch();
             }
             else
             {

Modified: felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/activator/Activator.java
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/activator/Activator.java?rev=1653078&r1=1653077&r2=1653078&view=diff
==============================================================================
--- felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/activator/Activator.java (original)
+++ felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/activator/Activator.java Mon Jan 19 19:10:24 2015
@@ -25,10 +25,13 @@ import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
+import org.apache.felix.gogo.api.CommandSessionListener;
 import org.apache.felix.gogo.runtime.CommandProcessorImpl;
 import org.apache.felix.gogo.runtime.CommandProxy;
-import org.apache.felix.gogo.api.CommandSessionListener;
 import org.apache.felix.gogo.runtime.threadio.ThreadIOImpl;
+import org.apache.felix.service.command.CommandProcessor;
+import org.apache.felix.service.command.Converter;
+import org.apache.felix.service.threadio.ThreadIO;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
@@ -36,10 +39,6 @@ import org.osgi.framework.Filter;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
-import org.apache.felix.service.command.CommandProcessor;
-import org.apache.felix.service.command.Converter;
-import org.apache.felix.service.command.Function;
-import org.apache.felix.service.threadio.ThreadIO;
 import org.osgi.util.tracker.ServiceTracker;
 
 public class Activator implements BundleActivator

Modified: felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/activator/EventAdminListener.java
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/activator/EventAdminListener.java?rev=1653078&r1=1653077&r2=1653078&view=diff
==============================================================================
--- felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/activator/EventAdminListener.java (original)
+++ felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/activator/EventAdminListener.java Mon Jan 19 19:10:24 2015
@@ -29,13 +29,10 @@ import org.osgi.util.tracker.ServiceTrac
 
 public class EventAdminListener implements CommandSessionListener
 {
-
-    private BundleContext bundleContext;
     private ServiceTracker tracker;
 
     public EventAdminListener(BundleContext bundleContext)
     {
-        this.bundleContext = bundleContext;
         tracker = new ServiceTracker(bundleContext, EventAdmin.class.getName(), null);
         tracker.open();
     }

Modified: felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/threadio/ThreadPrintStream.java
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/threadio/ThreadPrintStream.java?rev=1653078&r1=1653077&r2=1653078&view=diff
==============================================================================
--- felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/threadio/ThreadPrintStream.java (original)
+++ felix/trunk/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/threadio/ThreadPrintStream.java Mon Jan 19 19:10:24 2015
@@ -20,7 +20,6 @@ package org.apache.felix.gogo.runtime.th
 
 import java.io.IOException;
 import java.io.PrintStream;
-import java.io.InputStream;
 import java.util.Locale;
 
 public class ThreadPrintStream extends PrintStream

Modified: felix/trunk/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/Context.java
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/Context.java?rev=1653078&r1=1653077&r2=1653078&view=diff
==============================================================================
--- felix/trunk/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/Context.java (original)
+++ felix/trunk/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/Context.java Mon Jan 19 19:10:24 2015
@@ -68,9 +68,4 @@ public class Context extends CommandProc
         session.put(name, value);
     }
 
-    public Object get(String name)
-    {
-        return session.get(name);
-    }
-
 }

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=1653078&r1=1653077&r2=1653078&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 Mon Jan 19 19:10:24 2015
@@ -46,7 +46,7 @@ public class TestParser extends TestCase
 
         assertEquals("a", c.execute("echo a | capture"));
         assertEquals("a", c.execute("(echo a) | capture"));
-        assertEquals("a", c.execute("( (echo a) ) | capture"));
+        assertEquals("a", c.execute("((echo a)) | capture"));
     }
 
     public void testUnknownCommand() throws Exception

Modified: felix/trunk/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/TestTokenizer.java
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/TestTokenizer.java?rev=1653078&r1=1653077&r2=1653078&view=diff
==============================================================================
--- felix/trunk/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/TestTokenizer.java (original)
+++ felix/trunk/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/TestTokenizer.java Mon Jan 19 19:10:24 2015
@@ -18,20 +18,24 @@
  */
 package org.apache.felix.gogo.runtime;
 
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.net.URI;
 import java.util.HashMap;
 import java.util.Map;
 
-import org.apache.felix.gogo.runtime.Evaluate;
-import org.apache.felix.gogo.runtime.Parser;
-import org.apache.felix.gogo.runtime.SyntaxError;
-import org.apache.felix.gogo.runtime.Token;
-import org.apache.felix.gogo.runtime.Tokenizer;
-import org.apache.felix.gogo.runtime.Tokenizer.Type;
-
 import junit.framework.TestCase;
 
+import org.apache.felix.gogo.runtime.Tokenizer.Type;
+import org.apache.felix.gogo.runtime.threadio.ThreadIOImpl;
+import org.junit.Test;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
 public class TestTokenizer extends TestCase
 {
     private final Map<String, Object> vars = new HashMap<String, Object>();
@@ -58,6 +62,7 @@ public class TestTokenizer extends TestC
         };
     }
 
+    @Test
     public void testHello() throws Exception
     {
         testHello("hello world\n");
@@ -98,7 +103,8 @@ public class TestTokenizer extends TestC
         assertEquals(Type.NEWLINE, t.next());
         assertEquals(Type.EOT, t.next());
     }
-
+    
+    @Test
     public void testString() throws Exception
     {
         testString("'single $quote' \"double $quote\"\n");
@@ -116,6 +122,7 @@ public class TestTokenizer extends TestC
         assertEquals(Type.EOT, t.next());
     }
 
+    @Test
     public void testClosure() throws Exception
     {
         testClosure2("x = { echo '}' $args //comment's\n}\n");
@@ -127,6 +134,7 @@ public class TestTokenizer extends TestC
     /*
      * x = {echo $args};
      */
+    @Test
     private void testClosure2(CharSequence text) throws Exception
     {
         Tokenizer t = new Tokenizer(text);
@@ -147,6 +155,7 @@ public class TestTokenizer extends TestC
         return type;
     }
 
+    @Test
     public void testExpand() throws Exception
     {
         final URI home = new URI("/home/derek");
@@ -269,6 +278,7 @@ public class TestTokenizer extends TestC
         return Tokenizer.expand(word, evaluate);
     }
 
+    @Test
     public void testParser() throws Exception
     {
         new Parser("// comment\n" + "a=\"who's there?\"; ps -ef;\n" + "ls | \n grep y\n").program();
@@ -277,4 +287,43 @@ public class TestTokenizer extends TestC
         new Parser(new Token(Type.ARRAY, p1, (short) 0, (short) 0)).program();
     }
 
+    /**
+     * FELIX-4679 / FELIX-4671. 
+     */
+    @Test
+    public void testScriptFelix4679() throws Exception
+    {
+        String script = "addcommand system (((${.context} bundles) 0) loadclass java.lang.System)";
+
+        ThreadIOImpl tio = new ThreadIOImpl();
+        tio.start();
+
+        try
+        {
+            BundleContext bc = createMockContext();
+
+            CommandProcessorImpl processor = new CommandProcessorImpl(tio);
+            processor.addCommand("gogo", processor, "addcommand");
+            processor.addConstant(".context", bc);
+
+            CommandSessionImpl session = new CommandSessionImpl(processor, new ByteArrayInputStream(script.getBytes()), System.out, System.err);
+
+            Closure c = new Closure(session, null, script);
+            assertNull(c.execute(session, null));
+        }
+        finally
+        {
+            tio.stop();
+        }
+    }
+
+    private BundleContext createMockContext() throws ClassNotFoundException
+    {
+        Bundle systemBundle = mock(Bundle.class);
+        when(systemBundle.loadClass(eq("java.lang.System"))).thenReturn(System.class);
+
+        BundleContext bc = mock(BundleContext.class);
+        when(bc.getBundles()).thenReturn(new Bundle[] { systemBundle });
+        return bc;
+    }
 }

Modified: felix/trunk/gogo/shell/src/main/java/org/apache/felix/gogo/shell/Activator.java
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/shell/src/main/java/org/apache/felix/gogo/shell/Activator.java?rev=1653078&r1=1653077&r2=1653078&view=diff
==============================================================================
--- felix/trunk/gogo/shell/src/main/java/org/apache/felix/gogo/shell/Activator.java (original)
+++ felix/trunk/gogo/shell/src/main/java/org/apache/felix/gogo/shell/Activator.java Mon Jan 19 19:10:24 2015
@@ -23,6 +23,11 @@ import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+
 import org.apache.felix.service.command.CommandProcessor;
 import org.apache.felix.service.command.CommandSession;
 import org.apache.felix.service.command.Converter;
@@ -32,30 +37,28 @@ import org.osgi.framework.ServiceReferen
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.util.tracker.ServiceTracker;
 
-public class Activator implements BundleActivator, Runnable
+public class Activator implements BundleActivator
 {
     private BundleContext context;
     private ServiceTracker commandProcessorTracker;
-    private Set<ServiceRegistration> regs = new HashSet<ServiceRegistration>();
-    private CommandSession session;
-    private Shell shell;
-    private Thread thread;
+    private Set<ServiceRegistration> regs;
+
+    private ExecutorService executor;
 
-    public void start(final BundleContext ctxt) throws Exception
+    public Activator()
     {
-        context = ctxt;
-        commandProcessorTracker = processorTracker();
+        regs = new HashSet<ServiceRegistration>();
     }
 
-    public void stop(BundleContext context) throws Exception
+    public void start(BundleContext context) throws Exception
     {
-        if (thread != null)
-        {
-            thread.interrupt();
-        }
+        this.context = context;
+        this.commandProcessorTracker = createCommandProcessorTracker();
+        this.commandProcessorTracker.open();
+    }
 
-        commandProcessorTracker.close();
-        
+    public void stop(BundleContext context) throws Exception
+    {
         Iterator<ServiceRegistration> iterator = regs.iterator();
         while (iterator.hasNext())
         {
@@ -63,36 +66,31 @@ public class Activator implements Bundle
             reg.unregister();
             iterator.remove();
         }
+
+        stopShell();
+
+        this.commandProcessorTracker.close();
     }
 
-    public void run()
+    private ServiceTracker createCommandProcessorTracker()
     {
-        try
-        {
-            // wait for gosh command to be registered
-            for (int i = 0; (i < 100) && session.get("gogo:gosh") == null; ++i) {
-	            Thread.sleep(10);
-            }
-            
-            String args = context.getProperty("gosh.args");
-            args = (args == null) ? "" : args;
-            session.execute("gosh --login " + args);
-        }
-        catch (Exception e)
+        return new ServiceTracker(context, CommandProcessor.class.getName(), null)
         {
-            Object loc = session.get(".location");
-            if (null == loc || !loc.toString().contains(":"))
+            @Override
+            public Object addingService(ServiceReference reference)
             {
-                loc = "gogo";
+                CommandProcessor processor = (CommandProcessor) super.addingService(reference);
+                startShell(context, processor);
+                return processor;
             }
 
-            System.err.println(loc + ": " + e.getClass().getSimpleName() + ": " + e.getMessage());
-            e.printStackTrace();
-        }
-        finally
-        {
-            session.close();
-        }
+            @Override
+            public void removedService(ServiceReference reference, Object service)
+            {
+                stopShell();
+                super.removedService(reference, service);
+            }
+        };
     }
 
     private void startShell(BundleContext context, CommandProcessor processor)
@@ -102,9 +100,9 @@ public class Activator implements Bundle
 
         // register converters
         regs.add(context.registerService(Converter.class.getName(), new Converters(context), null));
-        
+
         // register commands
-        
+
         dict.put(CommandProcessor.COMMAND_FUNCTION, Builtin.functions);
         regs.add(context.registerService(Builtin.class.getName(), new Builtin(), dict));
 
@@ -116,42 +114,85 @@ public class Activator implements Bundle
 
         dict.put(CommandProcessor.COMMAND_FUNCTION, Telnet.functions);
         regs.add(context.registerService(Telnet.class.getName(), new Telnet(processor), dict));
-        
-        shell = new Shell(context, processor);
+
+        Shell shell = new Shell(context, processor);
         dict.put(CommandProcessor.COMMAND_FUNCTION, Shell.functions);
         regs.add(context.registerService(Shell.class.getName(), shell, dict));
-        
-        // start shell
-        session = processor.createSession(System.in, System.out, System.err);
-        thread = new Thread(this, "Gogo shell");
-        thread.start();
+
+        // start shell on a separate thread...
+        executor = Executors.newSingleThreadExecutor(new ThreadFactory()
+        {
+            public Thread newThread(Runnable runnable)
+            {
+                return new Thread(runnable, "Gogo shell");
+            }
+        });
+        executor.submit(new StartShellJob(context, processor));
     }
 
-    private ServiceTracker processorTracker()
+    private void stopShell()
     {
-        ServiceTracker t = new ServiceTracker(context, CommandProcessor.class.getName(),
-            null)
+        if (executor != null && !(executor.isShutdown() || executor.isTerminated()))
         {
-            @Override
-            public Object addingService(ServiceReference reference)
+            executor.shutdownNow();
+
+            try
             {
-                CommandProcessor processor = (CommandProcessor) super.addingService(reference);
-                startShell(context, processor);
-                return processor;
+                if (!executor.awaitTermination(5, TimeUnit.SECONDS))
+                {
+                    System.err.println("!!! FAILED TO STOP EXECUTOR !!!");
+                }
+            }
+            catch (InterruptedException e)
+            {
+                // Restore administration...
+                Thread.currentThread().interrupt();
             }
+            executor = null;
+        }
+    }
 
-            @Override
-            public void removedService(ServiceReference reference, Object service)
+    private static class StartShellJob implements Runnable
+    {
+        private final BundleContext context;
+        private final CommandProcessor processor;
+
+        public StartShellJob(BundleContext context, CommandProcessor processor)
+        {
+            this.context = context;
+            this.processor = processor;
+        }
+
+        public void run()
+        {
+            CommandSession session = processor.createSession(System.in, System.out, System.err);
+            try
             {
-                if (thread != null)
+                // wait for gosh command to be registered
+                for (int i = 0; (i < 100) && session.get("gogo:gosh") == null; ++i)
                 {
-                    thread.interrupt();
+                    TimeUnit.MILLISECONDS.sleep(10);
                 }
-                super.removedService(reference, service);
+
+                String args = context.getProperty("gosh.args");
+                args = (args == null) ? "" : args;
+                session.execute("gosh --login " + args);
             }
-        };
+            catch (Exception e)
+            {
+                Object loc = session.get(".location");
+                if (null == loc || !loc.toString().contains(":"))
+                {
+                    loc = "gogo";
+                }
 
-        t.open();
-        return t;
+                System.err.println(loc + ": " + e.getClass().getSimpleName() + ": " + e.getMessage());
+                e.printStackTrace();
+            }
+            finally
+            {
+                session.close();
+            }
+        }
     }
 }
\ No newline at end of file