[FELIX-4637] Gogo can't cope without several commands with defined service.ranking
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1624391 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 65eebcf..6f41986 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
@@ -29,8 +29,11 @@
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;
+import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArraySet;
import org.apache.felix.gogo.api.CommandSessionListener;
@@ -44,10 +47,11 @@
{
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>();
+ protected final ConcurrentMap<String, Map<Object, Integer>> commands = new ConcurrentHashMap<String, Map<Object, Integer>>();
+ protected final Map<String, Object> constants = new ConcurrentHashMap<String, Object>();
protected final ThreadIO threadIO;
protected final WeakHashMap<CommandSession, Object> sessions = new WeakHashMap<CommandSession, Object>();
+ protected boolean stopped;
public CommandProcessorImpl(ThreadIO tio)
{
@@ -58,6 +62,9 @@
{
synchronized (sessions)
{
+ if (stopped) {
+ throw new IllegalStateException("CommandProcessor has been stopped");
+ }
CommandSessionImpl session = new CommandSessionImpl(this, in, out, err);
sessions.put(session, null);
return session;
@@ -68,6 +75,7 @@
{
synchronized (sessions)
{
+ stopped = true;
for (CommandSession session : sessions.keySet())
{
session.close();
@@ -113,9 +121,9 @@
String cfunction = name.substring(colon);
boolean anyScope = (colon == 1 && name.charAt(0) == '*');
- Object cmd = commands.get(name);
+ Map<Object, Integer> cmdMap = commands.get(name);
- if (null == cmd && anyScope)
+ if (null == cmdMap && anyScope)
{
String scopePath = (null == path ? "*" : path.toString());
@@ -123,30 +131,37 @@
{
if (scope.equals("*"))
{
- synchronized (commands)
+ for (Entry<String, Map<Object, Integer>> entry : commands.entrySet())
{
- for (Entry<String, Object> entry : commands.entrySet())
+ if (entry.getKey().endsWith(cfunction))
{
- if (entry.getKey().endsWith(cfunction))
- {
- cmd = entry.getValue();
- break;
- }
+ cmdMap = entry.getValue();
+ break;
}
}
}
else
{
- cmd = commands.get(scope + cfunction);
- }
-
- if (cmd != null)
- {
- break;
+ cmdMap = commands.get(scope + cfunction);
+ if (cmdMap != null)
+ {
+ break;
+ }
}
}
}
+ Object cmd = null;
+ if (cmdMap != null && !cmdMap.isEmpty())
+ {
+ for (Entry<Object, Integer> e : cmdMap.entrySet())
+ {
+ if (cmd == null || e.getValue() > cmdMap.get(cmd))
+ {
+ cmd = e.getKey();
+ }
+ }
+ }
if ((null == cmd) || (cmd instanceof Function))
{
return (Function) cmd;
@@ -164,6 +179,11 @@
public void addCommand(String scope, Object target, Class<?> functions)
{
+ addCommand(scope, target, functions, 0);
+ }
+
+ public void addCommand(String scope, Object target, Class<?> functions, int ranking)
+ {
if (target == null)
{
return;
@@ -172,7 +192,7 @@
String[] names = getFunctions(functions);
for (String function : names)
{
- addCommand(scope, target, function);
+ addCommand(scope, target, function, ranking);
}
}
@@ -188,32 +208,44 @@
public void addCommand(String scope, Object target, String function)
{
- synchronized (commands)
+ addCommand(scope, target, function, 0);
+ }
+
+ public void addCommand(String scope, Object target, String function, int ranking)
+ {
+ String key = (scope + ":" + function).toLowerCase();
+ Map<Object, Integer> cmdMap = commands.get(key);
+ if (cmdMap == null)
{
- commands.put((scope + ":" + function).toLowerCase(), target);
+ commands.putIfAbsent(key, new LinkedHashMap<Object, Integer>());
+ cmdMap = commands.get(key);
}
+ cmdMap.put(target, ranking);
}
public void removeCommand(String scope, String function)
{
- String func = (scope + ":" + function).toLowerCase();
- synchronized (commands)
+ // TODO: WARNING: this method does remove all mapping for scope:function
+ String key = (scope + ":" + function).toLowerCase();
+ commands.remove(key);
+ }
+
+ public void removeCommand(String scope, String function, Object target)
+ {
+ // TODO: WARNING: this method does remove all mapping for scope:function
+ String key = (scope + ":" + function).toLowerCase();
+ Map<Object, Integer> cmdMap = commands.get(key);
+ if (cmdMap != null)
{
- commands.remove(func);
+ cmdMap.remove(target);
}
}
public void removeCommand(Object target)
{
- synchronized (commands)
+ for (Map<Object, Integer> cmdMap : commands.values())
{
- for (Iterator<Object> i = commands.values().iterator(); i.hasNext();)
- {
- if (i.next() == target)
- {
- i.remove();
- }
- }
+ cmdMap.remove(target);
}
}
@@ -243,14 +275,6 @@
return functions;
}
- protected void put(String name, Object target)
- {
- synchronized (commands)
- {
- commands.put(name, target);
- }
- }
-
public Object convert(Class<?> desiredType, Object in)
{
for (Converter c : converters)
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 f7652b0..37a26a8 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
@@ -19,7 +19,11 @@
package org.apache.felix.gogo.runtime.activator;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
import org.apache.felix.gogo.runtime.CommandProcessorImpl;
import org.apache.felix.gogo.runtime.CommandProxy;
@@ -27,6 +31,7 @@
import org.apache.felix.gogo.runtime.threadio.ThreadIOImpl;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
@@ -138,32 +143,50 @@
return new ServiceTracker(context, filter, null)
{
+ private final ConcurrentMap<ServiceReference, Map<String, CommandProxy>> proxies
+ = new ConcurrentHashMap<ServiceReference, Map<String, CommandProxy>>();
+
@Override
public Object addingService(ServiceReference reference)
{
Object scope = reference.getProperty(CommandProcessor.COMMAND_SCOPE);
Object function = reference.getProperty(CommandProcessor.COMMAND_FUNCTION);
+ Object ranking = reference.getProperty(Constants.SERVICE_RANKING);
List<Object> commands = new ArrayList<Object>();
+ int rank = 0;
+ if (ranking != null)
+ {
+ try
+ {
+ rank = Integer.parseInt(ranking.toString());
+ }
+ catch (NumberFormatException e)
+ {
+ // Ignore
+ }
+ }
if (scope != null && function != null)
{
+ Map<String, CommandProxy> proxyMap = new HashMap<String, CommandProxy>();
if (function.getClass().isArray())
{
for (Object f : ((Object[]) function))
{
- Function target = new CommandProxy(context, reference,
- f.toString());
- processor.addCommand(scope.toString(), target, f.toString());
+ CommandProxy target = new CommandProxy(context, reference, f.toString());
+ proxyMap.put(f.toString(), target);
+ processor.addCommand(scope.toString(), target, f.toString(), rank);
commands.add(target);
}
}
else
{
- Function target = new CommandProxy(context, reference,
- function.toString());
- processor.addCommand(scope.toString(), target, function.toString());
+ CommandProxy target = new CommandProxy(context, reference, function.toString());
+ proxyMap.put(function.toString(), target);
+ processor.addCommand(scope.toString(), target, function.toString(), rank);
commands.add(target);
}
+ proxies.put(reference, proxyMap);
return commands;
}
return null;
@@ -177,16 +200,10 @@
if (scope != null && function != null)
{
- if (!function.getClass().isArray())
+ Map<String, CommandProxy> proxyMap = proxies.remove(reference);
+ for (Map.Entry<String, CommandProxy> entry : proxyMap.entrySet())
{
- processor.removeCommand(scope.toString(), function.toString());
- }
- else
- {
- for (Object func : (Object[]) function)
- {
- processor.removeCommand(scope.toString(), func.toString());
- }
+ processor.removeCommand(scope.toString(), entry.getKey(), entry.getValue());
}
}