close all sessions when runtime is stopped (FELIX-2545).
quit console if session is closed.


git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@986322 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/CommandProcessorImpl.java b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/CommandProcessorImpl.java
index b79ba01..d3bb889 100644
--- a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/CommandProcessorImpl.java
+++ b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/CommandProcessorImpl.java
@@ -27,6 +27,7 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeSet;
+import java.util.WeakHashMap;
 import java.util.Map.Entry;
 
 import org.osgi.framework.BundleContext;
@@ -42,6 +43,7 @@
     protected final Map<String, Object> commands = new LinkedHashMap<String, Object>();
     protected final BundleContext context;
     protected final ThreadIO threadIO;
+    protected final WeakHashMap<CommandSession, Object> sessions = new WeakHashMap<CommandSession, Object>();
 
     public CommandProcessorImpl(ThreadIO tio, BundleContext context)
     {
@@ -54,9 +56,19 @@
 
     public CommandSession createSession(InputStream in, PrintStream out, PrintStream err)
     {
-        return new CommandSessionImpl(this, in, out, err);
+        CommandSessionImpl session = new CommandSessionImpl(this, in, out, err);
+        sessions.put(session, null);
+        return session;
     }
 
+    public void stop()
+    {
+        for (CommandSession session : sessions.keySet())
+        {
+            session.close();
+        }
+    }
+    
     public void addConverter(Converter c)
     {
         converters.add(c);
diff --git a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/CommandSessionImpl.java b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/CommandSessionImpl.java
index 02982a2..d32f10a 100644
--- a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/CommandSessionImpl.java
+++ b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/CommandSessionImpl.java
@@ -33,6 +33,7 @@
 
 public class CommandSessionImpl implements CommandSession, Converter
 {
+    public static final String SESSION_CLOSED = "session is closed";
     public static final String VARIABLES = ".variables";
     public static final String COMMANDS = ".commands";
     public static final String CONTEXT = ".context";
@@ -71,7 +72,7 @@
 
         if (closed)
         {
-            throw new IllegalStateException("session is closed");
+            throw new IllegalStateException(SESSION_CLOSED);
         }
 
         Closure impl = new Closure(this, null, commandline);
diff --git a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/activator/Activator.java b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/activator/Activator.java
index 0d9f286..e95fd2e 100644
--- a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/activator/Activator.java
+++ b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/activator/Activator.java
@@ -90,6 +90,7 @@
         commandTracker.close();
         converterTracker.close();
         threadio.stop();
+        processor.stop();
     }
 
     private ServiceTracker trackOSGiCommands(final BundleContext context)
diff --git a/gogo/shell/src/main/java/org/apache/felix/gogo/shell/Console.java b/gogo/shell/src/main/java/org/apache/felix/gogo/shell/Console.java
index 1f021e7..324a2d5 100644
--- a/gogo/shell/src/main/java/org/apache/felix/gogo/shell/Console.java
+++ b/gogo/shell/src/main/java/org/apache/felix/gogo/shell/Console.java
@@ -44,31 +44,43 @@
         {
             while (!quit)
             {
+                Object prompt = session.get("prompt");
+                if (prompt == null)
+                {
+                    prompt = "g! ";
+                }
+
+                CharSequence line = getLine(prompt.toString());
+
+                if (line == null)
+                {
+                    break;
+                }
+
                 try
                 {
-                    Object prompt = session.get("prompt");
-                    if (prompt == null)
-                    {
-                        prompt = "g! ";
-                    }
-
-                    CharSequence line = getLine(prompt.toString());
-
-                    if (line == null)
-                    {
-                        break;
-                    }
-
                     Object result = session.execute(line);
-                    session.put("_", result);    // set $_ to last result
+                    session.put("_", result); // set $_ to last result
 
-                    if (result != null && !Boolean.FALSE.equals(session.get(".Gogo.format")))
+                    if (result != null
+                        && !Boolean.FALSE.equals(session.get(".Gogo.format")))
                     {
                         out.println(session.format(result, Converter.INSPECT));
                     }
                 }
                 catch (Throwable e)
                 {
+                    final String SESSION_CLOSED = "session is closed";
+                    if ((e instanceof IllegalStateException) && SESSION_CLOSED.equals(e.getMessage()))
+                    {
+                        // FIXME: we assume IllegalStateException is because the session is closed;
+                        // but it may be for another reason, so we also check the message (yuk).
+                        // It would be better if the RFC-147 API threw a unique exception, such as
+                        // org.osgi.service.command.SessionClosedException
+                        out.println("gosh: " + e);
+                        quit = true;
+                    }
+                    
                     if (!quit)
                     {
                         session.put("exception", e);
@@ -79,7 +91,8 @@
                             loc = "gogo";
                         }
 
-                        out.println(loc + ": " + e.getClass().getSimpleName() + ": " + e.getMessage());
+                        out.println(loc + ": " + e.getClass().getSimpleName() + ": "
+                            + e.getMessage());
                     }
                 }
             }
@@ -106,7 +119,7 @@
             switch (c)
             {
                 case -1:
-                case 4:    // EOT, ^D from telnet
+                case 4: // EOT, ^D from telnet
                     quit = true;
                     break;
 
@@ -138,9 +151,4 @@
         return null;
     }
 
-    public void close()
-    {
-        quit = true;
-    }
-
 }