[FELIX-4363] The CommandSession get/set methods are not thread safe

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1552136 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 b48ec1c..65eebcf 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
@@ -42,7 +42,7 @@
 
 public class CommandProcessorImpl implements CommandProcessor
 {
-    protected final Set<Converter> converters = new HashSet<Converter>();
+    protected final Set<Converter> converters = new CopyOnWriteArraySet<Converter>();
     protected final Set<CommandSessionListener> listeners = new CopyOnWriteArraySet<CommandSessionListener>();
     protected final Map<String, Object> commands = new LinkedHashMap<String, Object>();
     protected final Map<String, Object> constants = new HashMap<String, Object>();
@@ -56,16 +56,22 @@
 
     public CommandSession createSession(InputStream in, PrintStream out, PrintStream err)
     {
-        CommandSessionImpl session = new CommandSessionImpl(this, in, out, err);
-        sessions.put(session, null);
-        return session;
+        synchronized (sessions)
+        {
+            CommandSessionImpl session = new CommandSessionImpl(this, in, out, err);
+            sessions.put(session, null);
+            return session;
+        }
     }
 
     public void stop()
     {
-        for (CommandSession session : sessions.keySet())
+        synchronized (sessions)
         {
-            session.close();
+            for (CommandSession session : sessions.keySet())
+            {
+                session.close();
+            }
         }
     }
 
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 447e735..3f6d435 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
@@ -27,11 +27,14 @@
 import java.lang.reflect.Modifier;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 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;
@@ -50,7 +53,7 @@
     PrintStream err;
     
     private final CommandProcessorImpl processor;
-    protected final Map<String, Object> variables = new HashMap<String, Object>();
+    protected final Map<String, Object> variables = new ConcurrentHashMap<String, Object>();
     private boolean closed;
 
     protected CommandSessionImpl(CommandProcessorImpl shell, InputStream in, PrintStream out, PrintStream err)
@@ -107,7 +110,7 @@
         // there is no API to list all variables, so overload name == null
         if (name == null || VARIABLES.equals(name))
         {
-            return variables.keySet();
+            return Collections.unmodifiableSet(variables.keySet());
         }
 
         if (COMMANDS.equals(name))
@@ -115,30 +118,34 @@
             return processor.getCommands();
         }
 
-        if( processor.constants.containsKey(name) )
+        Object val = processor.constants.get(name);
+        if( val != null )
         {
-            return processor.constants.get(name);
+            return val;
         }
 
-        if (variables.containsKey("#" + name))
+        val = variables.get("#" + name);
+        if (val instanceof Function)
         {
-            Object f = variables.get("#" + name);
-            if (f instanceof Function)
+            try
             {
-                try
-                {
-                    f = ((Function) f).execute(this, null);
-                }
-                catch (Exception e)
-                {
-                    // Ignore
-                }
+                val = ((Function) val).execute(this, null);
             }
-            return f;
+            catch (Exception e)
+            {
+                // Ignore
+            }
+            return val;
         }
-        if (variables.containsKey(name))
+        else if( val != null )
         {
-            return variables.get(name);
+            return val;
+        }
+
+        val = variables.get(name);
+        if( val != null )
+        {
+            return val;
         }
 
         return processor.getCommand(name, variables.get("SCOPE"));