add felix command adaptor (FELIX-1671)


git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@820781 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Activator.java b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Activator.java
index bca9811..0fae433 100644
--- a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Activator.java
+++ b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Activator.java
@@ -32,9 +32,11 @@
 import org.osgi.service.threadio.ThreadIO;
 import org.osgi.util.tracker.ServiceTracker;
 
+import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 public class Activator implements BundleActivator
 {
@@ -45,6 +47,8 @@
     private ServiceRegistration threadioRegistration;
     private ServiceTracker converterTracker;
     private ServiceTracker commandTracker;
+    private ServiceTracker felixTracker;
+    private Map<ServiceReference, ServiceRegistration> regs = new HashMap<ServiceReference, ServiceRegistration>();
 
     public void start(final BundleContext context) throws Exception
     {
@@ -76,6 +80,7 @@
             }
         };
         converterTracker.open();
+        
         commandTracker = new ServiceTracker(context, context.createFilter("(&(osgi.command.scope=*)(osgi.command.function=*))"), null) {
             @Override
             public Object addingService(ServiceReference reference)
@@ -116,6 +121,32 @@
             }
         };
         commandTracker.open();
+        
+        felixTracker = new ServiceTracker(context, FelixCommandAdaptor.FELIX_COMMAND, null) {
+            @Override
+            public Object addingService(ServiceReference ref) {
+                Object felixCommand = super.addingService(ref);
+                try {
+                    FelixCommandAdaptor adaptor = new FelixCommandAdaptor(felixCommand);
+                    regs.put(ref, context.registerService(FelixCommandAdaptor.class.getName(), adaptor,
+                            adaptor.getAttributes()));
+                    return felixCommand;
+                } catch (Exception e) {
+                    System.err.println("felixcmd: " + e);
+                    return null;
+                }
+            }
+
+            @Override
+            public void removedService(ServiceReference reference, Object service) {
+                ServiceRegistration reg = regs.remove(reference);
+                if (reg != null)
+                    reg.unregister();
+                super.removedService(reference, service);
+            }
+        };
+        felixTracker.open();
+        
         threadioRegistration = context.registerService(ThreadIO.class.getName(), threadio, new Hashtable());
         shellRegistration = context.registerService(CommandProcessor.class.getName(), shell, new Hashtable());
     }
@@ -135,5 +166,6 @@
         threadio.stop();
         converterTracker.close();
         commandTracker.close();
+        felixTracker.close();
     }
 }
diff --git a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/FelixCommandAdaptor.java b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/FelixCommandAdaptor.java
new file mode 100644
index 0000000..174e7dd
--- /dev/null
+++ b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/FelixCommandAdaptor.java
@@ -0,0 +1,61 @@
+package org.apache.felix.gogo.runtime;
+
+import java.io.PrintStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.osgi.service.command.CommandProcessor;
+
+public class FelixCommandAdaptor {
+    public static final String FELIX_COMMAND = "org.apache.felix.shell.Command";
+    private final Object felixCommand;
+    private Method execute;
+    private String help;
+    private String name;
+    private String usage;
+
+    public FelixCommandAdaptor(Object felixCommand) throws Exception {
+        this.felixCommand = felixCommand;
+        Class<?> c = felixCommand.getClass();
+        Class<?>[] parms = { String.class, PrintStream.class, PrintStream.class};
+        execute = c.getMethod("execute", parms);
+
+        Method name = c.getMethod("getName", (Class[]) null);
+        this.name = (String) name.invoke(felixCommand, (Object[]) null);
+
+        Method help = c.getMethod("getShortDescription", (Class[]) null);
+        this.help = (String) help.invoke(felixCommand, (Object[]) null);
+
+        Method usage = c.getMethod("getUsage", (Class[]) null);
+        this.usage = (String) usage.invoke(felixCommand, (Object[]) null);
+    }
+
+    public void _main(String[] argv) throws Exception {
+        StringBuilder buf = new StringBuilder();
+        for (String arg : argv) {
+            if (buf.length() > 0)
+                buf.append(' ');
+            buf.append(arg);
+        }
+        
+        try {
+            Object[] args = { buf.toString(), System.out, System.err};
+            execute.invoke(felixCommand, args);
+        } catch (InvocationTargetException e) {
+            Throwable cause = e.getCause();
+            if (cause instanceof Exception)
+                throw (Exception) cause;
+            throw e;
+        }
+    }
+
+    public Dictionary<String, Object> getAttributes() {
+        Dictionary<String, Object> dict = new Hashtable<String, Object>();
+        dict.put(CommandProcessor.COMMAND_SCOPE, "felix");
+        dict.put(CommandProcessor.COMMAND_FUNCTION, name);
+        return dict;
+    }
+
+}