Add support for Gogo. (FELIX-2544)


git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@986336 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/shell.remote/pom.xml b/shell.remote/pom.xml
index 5f6b3c7..9aa49e5 100644
--- a/shell.remote/pom.xml
+++ b/shell.remote/pom.xml
@@ -27,7 +27,7 @@
     <packaging>bundle</packaging>
     <name>Apache Felix Remote Shell</name>
     <description>
-        A simple remote textual user interface for Felix' shell service.
+        Provide remote access to Felix Shell or Gogo.
     </description>
     <version>1.0.5-SNAPSHOT</version>
     <artifactId>org.apache.felix.shell.remote</artifactId>
@@ -47,6 +47,11 @@
             <artifactId>org.apache.felix.shell</artifactId>
             <version>1.0.0</version>
         </dependency>
+        <dependency>
+            <groupId>${pom.groupId}</groupId>
+            <artifactId>org.apache.felix.gogo.runtime</artifactId>
+            <version>0.6.0</version>
+        </dependency>
     </dependencies>
     <build>
         <plugins>
@@ -65,9 +70,9 @@
                         <Private-Package>
                             org.apache.felix.shell.remote.*
                         </Private-Package>
-                        <Import-Package>
-                            org.osgi.service.log;resolution:=optional,* 
-                        </Import-Package>
+                        <DynamicImport-Package>
+                            org.apache.felix.service.command,org.apache.felix.shell,org.osgi.service.log
+                        </DynamicImport-Package>
                     </instructions>
                 </configuration>
             </plugin>
diff --git a/shell.remote/src/main/java/org/apache/felix/shell/remote/ServiceMediator.java b/shell.remote/src/main/java/org/apache/felix/shell/remote/ServiceMediator.java
index 994a4ff..f28fa99 100644
--- a/shell.remote/src/main/java/org/apache/felix/shell/remote/ServiceMediator.java
+++ b/shell.remote/src/main/java/org/apache/felix/shell/remote/ServiceMediator.java
@@ -16,14 +16,7 @@
  */
 package org.apache.felix.shell.remote;
 
-import org.apache.felix.shell.ShellService;
-import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceEvent;
-import org.osgi.framework.ServiceListener;
-import org.osgi.framework.ServiceReference;
 import org.osgi.service.log.LogService;
 import org.osgi.util.tracker.ServiceTracker;
 
@@ -37,6 +30,7 @@
     private final BundleContext m_context;
     private final ServiceTracker m_logTracker;
     private final ServiceTracker m_shellTracker;
+    private final ServiceTracker m_cpTracker;
 
     ServiceMediator(BundleContext context)
     {
@@ -45,21 +39,36 @@
             ? m_context.getBundle().getLocation()
             : m_context.getBundle().getSymbolicName();
         m_bundleId = m_context.getBundle().getBundleId();
-        ServiceTracker logTracker = null;
+        m_logTracker = new ServiceTracker(
+            m_context, "org.osgi.service.log.LogService", null);
+        m_logTracker.open();
+        m_shellTracker = new ServiceTracker(
+            m_context, "org.apache.felix.shell.ShellService", null);
+        m_shellTracker.open();
+        m_cpTracker = new ServiceTracker(
+            m_context, "org.apache.felix.service.command.CommandProcessor", null);
+        m_cpTracker.open();
+    }
+
+    public Object getCommandProcessor(long wait)
+    {
+        Object svcObj = null;
         try
         {
-            logTracker = new ServiceTracker(m_context, LogService.class.getName(), null);
-            logTracker.open();
+            if (wait < 0)
+            {
+                svcObj = m_cpTracker.getService();
+            }
+            else
+            {
+                svcObj = m_cpTracker.waitForService(wait);
+            }
         }
-        catch (Throwable ex)
+        catch (InterruptedException e)
         {
-            // This means we don't have access to the log service package since it
-            // is optional, so don't track log services.
-            logTracker = null;
+            e.printStackTrace(System.err);
         }
-        m_logTracker = logTracker;
-        m_shellTracker = new ServiceTracker(m_context, ShellService.class.getName(), null);
-        m_shellTracker.open();
+        return svcObj;
     }
 
     /**
@@ -68,55 +77,53 @@
      * @param wait time in milliseconds to wait for the reference if it isn't available.
      * @return the reference to the <tt>ShellService</tt> as obtained from the OSGi service layer.
      */
-    public ShellService getFelixShellService(long wait)
+    public Object getShellService(long wait)
     {
-        ShellService shell = null;
+        Object svcObj = null;
         try
         {
             if (wait < 0)
             {
-                shell = (ShellService) m_shellTracker.getService();
+                svcObj = m_shellTracker.getService();
             }
             else
             {
-                shell = (ShellService) m_shellTracker.waitForService(wait);
+                svcObj = m_shellTracker.waitForService(wait);
+            }
+
+            return svcObj;
+        }
+        catch (InterruptedException e)
+        {
+            e.printStackTrace(System.err);
+        }
+        return svcObj;
+    }//getFelixShellService
+
+    public Object getLogService(long wait)
+    {
+        Object svcObj = null;
+        try
+        {
+            if (wait < 0)
+            {
+                svcObj = m_logTracker.getService();
+            }
+            else
+            {
+                svcObj = m_logTracker.waitForService(wait);
             }
         }
         catch (InterruptedException e)
         {
             e.printStackTrace(System.err);
         }
-
-        return shell;
-    }//getFelixShellService
-
-    public Object getLogServiceLatch(long wait)
-    {
-        Object log = null;
-        if (m_logTracker != null)
-        {
-            try
-            {
-                if (wait < 0)
-                {
-                    log = m_logTracker.getService();
-                }
-                else
-                {
-                    log = m_logTracker.waitForService(wait);
-                }
-            }
-            catch (InterruptedException e)
-            {
-                e.printStackTrace(System.err);
-            }
-        }
-        return log;
+        return svcObj;
     }//getLogService
 
     public void info(String msg)
     {
-        Object log = getLogServiceLatch(NO_WAIT);
+        Object log = getLogService(NO_WAIT);
         if (log != null)
         {
             ((LogService) log).log(LogService.LOG_INFO, msg);
@@ -129,7 +136,7 @@
 
     public void error(String msg, Throwable t)
     {
-        Object log = getLogServiceLatch(NO_WAIT);
+        Object log = getLogService(NO_WAIT);
         if (log != null)
         {
             ((LogService) log).log(LogService.LOG_ERROR, msg);
@@ -142,7 +149,7 @@
 
     public void error(String msg)
     {
-        Object log = getLogServiceLatch(NO_WAIT);
+        Object log = getLogService(NO_WAIT);
         if (log != null)
         {
             ((LogService) log).log(LogService.LOG_ERROR, msg);
@@ -155,7 +162,7 @@
 
     public void debug(String msg)
     {
-        Object log = getLogServiceLatch(NO_WAIT);
+        Object log = getLogService(NO_WAIT);
         if (log != null)
         {
             ((LogService) log).log(LogService.LOG_DEBUG, msg);
@@ -168,7 +175,7 @@
 
     public void warn(String msg)
     {
-        Object log = getLogServiceLatch(NO_WAIT);
+        Object log = getLogService(NO_WAIT);
         if (log != null)
         {
             ((LogService) log).log(LogService.LOG_WARNING, msg);
@@ -219,6 +226,7 @@
             m_logTracker.close();
         }
         m_shellTracker.close();
+        m_cpTracker.close();
     }//deactivate
 
     public static long WAIT_UNLIMITED = 0;
diff --git a/shell.remote/src/main/java/org/apache/felix/shell/remote/Shell.java b/shell.remote/src/main/java/org/apache/felix/shell/remote/Shell.java
index 6530aa3..43e230c 100644
--- a/shell.remote/src/main/java/org/apache/felix/shell/remote/Shell.java
+++ b/shell.remote/src/main/java/org/apache/felix/shell/remote/Shell.java
@@ -18,8 +18,9 @@
 
 import java.io.BufferedReader;
 import java.io.IOException;
-import java.io.PrintStream;
 import java.net.Socket;
+import org.apache.felix.service.command.CommandProcessor;
+import org.apache.felix.service.command.CommandSession;
 
 import org.apache.felix.shell.ShellService;
 
@@ -62,61 +63,32 @@
     {
         m_owner.registerConnection(this);
 
+        String msg = null;
+
         try
         {
             m_out = new TerminalPrintStream(
                 m_owner.getServices(), m_socket.getOutputStream());
-            BufferedReader in = new BufferedReader(
-                new TerminalReader(m_socket.getInputStream(), m_out));
-            ReentrantLock lock = new ReentrantLock();
 
-            // Print welcome banner.
-            m_out.println();
-            m_out.println("Felix Remote Shell Console:");
-            m_out.println("============================");
-            m_out.println("");
+            Object obj = null;
 
-            do
+            if ((obj = m_owner.getServices().getCommandProcessor(ServiceMediator.NO_WAIT))
+                != null)
             {
-                String line = "";
-                try
-                {
-                    m_out.print("-> ");
-                    line = in.readLine();
-                    //make sure to capture end of stream
-                    if (line == null)
-                    {
-                        m_out.println("exit");
-                        return;
-                    }
-                }
-                catch (Exception ex)
-                {
-                    return;
-                }
-
-                line = line.trim();
-                if (line.equalsIgnoreCase("exit") || line.equalsIgnoreCase("disconnect"))
-                {
-                    return;
-                }
-
-                ShellService shs = m_owner.getServices().getFelixShellService(ServiceMediator.NO_WAIT);
-                try
-                {
-                    lock.acquire();
-                    shs.executeCommand(line, m_out, m_out);
-                }
-                catch (Exception ex)
-                {
-                    m_owner.getServices().error("Shell::run()", ex);
-                }
-                finally
-                {
-                    lock.release();
-                }
+                CommandProcessor cp = (CommandProcessor) obj;
+                CommandSession session =
+                    cp.createSession(m_socket.getInputStream(), m_out, m_out);
+                startGogoShell(session);
             }
-            while (true);
+            else if ((obj = m_owner.getServices().getShellService(ServiceMediator.NO_WAIT))
+                != null)
+            {
+                startFelixShell();
+            }
+            else
+            {
+                msg = "No shell services available...exiting.";
+            }
         }
         catch (IOException ex)
         {
@@ -125,10 +97,82 @@
         finally
         {
             // no need to clean up in/out, since exit does it all
-            exit(null);
+            exit(msg);
         }
     }//run
 
+    private void startGogoShell(CommandSession session)
+    {
+        try
+        {
+            session.execute("gosh --login --noshutdown");
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+        finally
+        {
+            session.close();
+        }
+    }
+
+    private void startFelixShell() throws IOException
+    {
+        BufferedReader in = new BufferedReader(
+            new TerminalReader(m_socket.getInputStream(), m_out));
+        ReentrantLock lock = new ReentrantLock();
+
+        // Print welcome banner.
+        m_out.println();
+        m_out.println("Felix Remote Shell Console:");
+        m_out.println("============================");
+        m_out.println("");
+
+        do
+        {
+            String line = "";
+            try
+            {
+                m_out.print("-> ");
+                line = in.readLine();
+                //make sure to capture end of stream
+                if (line == null)
+                {
+                    m_out.println("exit");
+                    return;
+                }
+            }
+            catch (Exception ex)
+            {
+                return;
+            }
+
+            line = line.trim();
+            if (line.equalsIgnoreCase("exit") || line.equalsIgnoreCase("disconnect"))
+            {
+                return;
+            }
+
+            ShellService shs = (ShellService)
+                m_owner.getServices().getShellService(ServiceMediator.NO_WAIT);
+            try
+            {
+                lock.acquire();
+                shs.executeCommand(line, m_out, m_out);
+            }
+            catch (Exception ex)
+            {
+                m_owner.getServices().error("Shell::run()", ex);
+            }
+            finally
+            {
+                lock.release();
+            }
+        }
+        while (true);
+    }
+
     private void exit(String message)
     {
         // farewell message