FELIX-1102: make gshell-core really independant of the MainService

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@769799 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/LocalConsole.java b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/LocalConsole.java
index 98c7193..6f9a8ee 100644
--- a/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/LocalConsole.java
+++ b/karaf/gshell/gshell-core/src/main/java/org/apache/servicemix/kernel/gshell/core/LocalConsole.java
@@ -21,14 +21,15 @@
 import java.util.Arrays;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
+import java.lang.reflect.Method;
 
 import org.apache.geronimo.gshell.notification.ExitNotification;
 import org.apache.geronimo.gshell.shell.Shell;
-import org.apache.servicemix.kernel.main.spi.MainService;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleException;
 import org.osgi.framework.FrameworkEvent;
 import org.osgi.framework.FrameworkListener;
+import org.osgi.util.tracker.ServiceTracker;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.osgi.context.BundleContextAware;
@@ -43,9 +44,9 @@
 
     private BundleContext bundleContext;
 
-    private MainService mainService;
-
     private CountDownLatch frameworkStarted;
+
+    private ServiceTracker mainServiceTracker;
     
     public BundleContext getBundleContext() {
         return bundleContext;
@@ -55,14 +56,6 @@
         this.bundleContext = bundleContext;
     }
 
-    public MainService getMainService() {
-        return mainService;
-    }
-
-    public void setMainService(MainService mainService) {
-        this.mainService = mainService;
-    }
-
     public Shell getShell() {
         return shell;
     }
@@ -80,6 +73,9 @@
     }
 
     public void init() {
+        mainServiceTracker = new ServiceTracker(bundleContext, "org.apache.servicemix.kernel.main.spi.MainService", null);
+        mainServiceTracker.open();
+
         shell.getContext().getVariables().set("gshell.username", "smx");
         frameworkStarted = new CountDownLatch(1);
 		getBundleContext().addFrameworkListener(new FrameworkListener(){
@@ -96,6 +92,7 @@
     }
 
     public void destroy() {
+        mainServiceTracker.close();
         if (createLocalShell) {
             shell.close();
         }
@@ -103,7 +100,7 @@
 
     public void run() {
         try {
-            String[] args = mainService.getArgs();
+            String[] args = getMainServiceArgs();
             // If a command was specified on the command line, then just execute that command.
             if (args != null && args.length > 0) {
                 waitForFrameworkToStart();
@@ -113,26 +110,20 @@
                     sb.append(arg).append(" ");
                 }
                 Object value = shell.execute(sb.toString());
-                if (mainService != null) {
-                    if (value instanceof Number) {
-                        mainService.setExitCode(((Number) value).intValue());
-                    } else {
-                        mainService.setExitCode(value != null ? 1 : 0);
-                    }
-                    log.info("Exiting shell due to terminated command");
+                if (value instanceof Number) {
+                    setMainServiceExitCode(((Number) value).intValue());
+                } else {
+                    setMainServiceExitCode(value != null ? 1 : 0);
                 }
+                log.info("Exiting shell due to terminated command");
             } else {
                 shell.run();
             }
         } catch (ExitNotification e) {
-            if (mainService != null) {
-                mainService.setExitCode(0);
-            }
+            setMainServiceExitCode(0);
             log.info("Exiting shell due received exit notification");
         } catch (Throwable e) {
-            if (mainService != null) {
-                mainService.setExitCode(-1);
-            }
+            setMainServiceExitCode(-1);
             log.error("Exiting shell due to caught exception " + e, e);
         } finally {
             try {
@@ -142,6 +133,31 @@
         }
     }
 
+    private String[] getMainServiceArgs() {
+        try {
+            Object mainService = mainServiceTracker.getService();
+            if (mainService != null) {
+                Method mth = mainService.getClass().getMethod("getArgs");
+                return (String[]) mth.invoke(mainService);
+            }
+        } catch (Throwable t) {
+            log.debug("Error getting MainService args", t);
+        }
+        return null;
+    }
+
+    private void setMainServiceExitCode(int exitCode) {
+        try {
+            Object mainService = mainServiceTracker.getService();
+            if (mainService != null) {
+                Method mth = mainService.getClass().getMethod("setExitCode", int.class);
+                mth.invoke(mainService, exitCode);
+            }
+        } catch (Throwable t) {
+            log.debug("Error setting MainService exit code", t);
+        }
+    }
+
     /**
      * Blocks until the framework has finished starting.  We do this so that any installed
      * bundles for commands get fully registered.
diff --git a/karaf/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-local.xml b/karaf/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-local.xml
index a047339..4c4b23f 100644
--- a/karaf/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-local.xml
+++ b/karaf/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-local.xml
@@ -39,12 +39,9 @@
         <constructor-arg ref="localShellWrapped" />
     </bean>
 
-    <osgi:reference id="mainService" interface="org.apache.servicemix.kernel.main.spi.MainService"/>
-
     <bean id="localConsole" class="org.apache.servicemix.kernel.gshell.core.LocalConsole">
         <property name="createLocalShell" value="${servicemix.startLocalConsole}"/>
         <property name="shell" ref="localShell"/>
-        <property name="mainService" ref="mainService" />
     </bean>
 
 </beans>
\ No newline at end of file