You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicemix.apache.org by gn...@apache.org on 2008/09/25 20:58:57 UTC

svn commit: r699054 - in /servicemix/smx4/kernel/trunk: client/src/main/java/org/apache/servicemix/kernel/client/ gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/remote/client/ gshell/gshell-core/src/main/resources/META-INF/spring/ gshell/g...

Author: gnodet
Date: Thu Sep 25 11:58:57 2008
New Revision: 699054

URL: http://svn.apache.org/viewvc?rev=699054&view=rev
Log:
SMX4KNL-100: The client shell does not close when running 'osgi shutdown' command

Added:
    servicemix/smx4/kernel/trunk/client/src/main/java/org/apache/servicemix/kernel/client/RshClient.java
    servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/remote/client/SpringRshClient.java
Modified:
    servicemix/smx4/kernel/trunk/client/src/main/java/org/apache/servicemix/kernel/client/Main.java
    servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/remote/client/SpringRshCommand.java
    servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-remote.xml
    servicemix/smx4/kernel/trunk/gshell/gshell-osgi/src/main/java/org/apache/geronimo/gshell/osgi/Shutdown.java

Modified: servicemix/smx4/kernel/trunk/client/src/main/java/org/apache/servicemix/kernel/client/Main.java
URL: http://svn.apache.org/viewvc/servicemix/smx4/kernel/trunk/client/src/main/java/org/apache/servicemix/kernel/client/Main.java?rev=699054&r1=699053&r2=699054&view=diff
==============================================================================
--- servicemix/smx4/kernel/trunk/client/src/main/java/org/apache/servicemix/kernel/client/Main.java (original)
+++ servicemix/smx4/kernel/trunk/client/src/main/java/org/apache/servicemix/kernel/client/Main.java Thu Sep 25 11:58:57 2008
@@ -17,14 +17,13 @@
 package org.apache.servicemix.kernel.client;
 
 import java.net.URI;
+import java.net.URL;
 import java.util.List;
 import java.util.LinkedList;
-import java.io.Reader;
 import java.io.InputStreamReader;
 import java.io.BufferedReader;
 
 import org.apache.geronimo.gshell.remote.crypto.CryptoContext;
-import org.apache.geronimo.gshell.remote.client.RshClient;
 import org.apache.geronimo.gshell.remote.client.RemoteExecuteException;
 import org.apache.geronimo.gshell.remote.client.handler.EchoHandler;
 import org.apache.geronimo.gshell.remote.client.handler.ClientMessageHandler;
@@ -33,7 +32,6 @@
 import org.apache.geronimo.gshell.whisper.transport.TransportFactoryLocator;
 import org.apache.geronimo.gshell.whisper.transport.tcp.SpringTcpTransportFactory;
 import org.apache.geronimo.gshell.whisper.stream.StreamFeeder;
-import org.apache.geronimo.gshell.layout.NotFoundException;
 import org.apache.geronimo.gshell.ExitNotification;
 
 /**
@@ -80,7 +78,11 @@
             CryptoContext context = new CryptoContext("RSA", null);
             List<ClientMessageHandler> handlers = new LinkedList<ClientMessageHandler>();
             handlers.add(new EchoHandler());
-            client = new RshClient(context, new Locator(), handlers);
+            client = new RshClient(context, new Locator(), handlers) {
+                protected void onSessionClosed() {
+                    System.exit(2);
+                }
+            };
 
             client.initialize();
             client.connect(address, new URI("tcp://0.0.0.0:0"));

Added: servicemix/smx4/kernel/trunk/client/src/main/java/org/apache/servicemix/kernel/client/RshClient.java
URL: http://svn.apache.org/viewvc/servicemix/smx4/kernel/trunk/client/src/main/java/org/apache/servicemix/kernel/client/RshClient.java?rev=699054&view=auto
==============================================================================
--- servicemix/smx4/kernel/trunk/client/src/main/java/org/apache/servicemix/kernel/client/RshClient.java (added)
+++ servicemix/smx4/kernel/trunk/client/src/main/java/org/apache/servicemix/kernel/client/RshClient.java Thu Sep 25 11:58:57 2008
@@ -0,0 +1,293 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.servicemix.kernel.client;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URI;
+import java.util.List;
+
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.LoginContext;
+
+import org.apache.geronimo.gshell.remote.client.auth.RemoteLoginModule;
+import org.apache.geronimo.gshell.remote.client.handler.ClientMessageHandler;
+import org.apache.geronimo.gshell.remote.client.handler.ClientSessionContext;
+import org.apache.geronimo.gshell.remote.client.RemoteExecuteException;
+import org.apache.geronimo.gshell.remote.crypto.CryptoContext;
+import org.apache.geronimo.gshell.remote.jaas.JaasConfigurationHelper;
+import org.apache.geronimo.gshell.remote.jaas.UsernamePasswordCallbackHandler;
+import org.apache.geronimo.gshell.remote.message.CloseShellMessage;
+import org.apache.geronimo.gshell.remote.message.ConnectMessage;
+import org.apache.geronimo.gshell.remote.message.EchoMessage;
+import org.apache.geronimo.gshell.remote.message.ExecuteMessage;
+import org.apache.geronimo.gshell.remote.message.OpenShellMessage;
+import org.apache.geronimo.gshell.whisper.message.Message;
+import org.apache.geronimo.gshell.whisper.message.MessageHandler;
+import org.apache.geronimo.gshell.whisper.transport.Session;
+import org.apache.geronimo.gshell.whisper.transport.Transport;
+import org.apache.geronimo.gshell.whisper.transport.TransportFactory;
+import org.apache.geronimo.gshell.whisper.transport.TransportFactoryLocator;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.handler.demux.DemuxingIoHandler;
+import org.codehaus.plexus.component.annotations.Component;
+import org.codehaus.plexus.component.annotations.Requirement;
+import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
+import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Provides support for the client-side of the remote shell protocol.
+ *
+ * @version $Rev: 638824 $ $Date: 2008-03-19 14:30:40 +0100 (Wed, 19 Mar 2008) $
+ */
+@Component(role=RshClient.class, instantiationStrategy="per-lookup")
+public class RshClient
+    implements Initializable
+{
+    private final Logger log = LoggerFactory.getLogger(getClass());
+
+    @Requirement
+    private CryptoContext crypto;
+
+    @Requirement
+    private TransportFactoryLocator locator;
+
+    private Transport transport;
+
+    private Session session;
+
+    @Requirement(role=ClientMessageHandler.class)
+    private List<ClientMessageHandler> handlers;
+
+    public RshClient() {
+    }
+
+    public RshClient(final CryptoContext crypto, final TransportFactoryLocator locator, final List<ClientMessageHandler> handlers) {
+        this.crypto = crypto;
+        this.locator = locator;
+        this.handlers = handlers;
+    }
+
+    public void initialize() throws InitializationException {
+        new JaasConfigurationHelper("client.login.conf").initialize();
+    }
+
+    public void connect(final URI remote, final URI local) throws Exception {
+        TransportFactory factory = locator.locate(remote);
+
+        transport = factory.connect(remote, local, new Handler());
+        session = transport.getSession();
+
+        log.debug("Connected to: {}", remote);
+    }
+
+    public InputStream getInputStream() {
+        return session.getInputStream();
+    }
+
+    public OutputStream getOutputStream() {
+        return session.getOutputStream();
+    }
+
+    public Transport getTransport() {
+        return transport;
+    }
+
+    public void close() {
+        transport.close();
+    }
+
+    public void login(final String username, final String password) throws Exception {
+        doHandshake();
+        doLogin(username, password);
+    }
+
+    private void doHandshake() throws Exception {
+        log.debug("Handshaking");
+
+        ClientSessionContext context = ClientSessionContext.BINDER.lookup(session.getSession());
+
+        Message response = session.request(new ConnectMessage(crypto.getPublicKey()));
+
+        if (response instanceof ConnectMessage.Result) {
+            ConnectMessage.Result result = (ConnectMessage.Result)response;
+            context.pk = result.getPublicKey();
+        }
+        else {
+            throw new InternalError("Unexpected handshake response: " + response);
+        }
+    }
+
+    private void doLogin(final String username, final String password) throws Exception {
+        log.debug("Logging in: {}", username);
+
+        ClientSessionContext context = ClientSessionContext.BINDER.lookup(session.getSession());
+
+        CallbackHandler callbackHandler = new UsernamePasswordCallbackHandler(username, password);
+        LoginContext loginContext = new LoginContext("RshClient", callbackHandler);
+
+        RemoteLoginModule.setTransport(transport);
+        try {
+            loginContext.login();
+        }
+        finally {
+            RemoteLoginModule.unsetTransport();
+        }
+
+        context.subject = loginContext.getSubject();
+        log.debug("Subject: {}", context.subject);
+    }
+
+    public void echo(final String text) throws Exception {
+        assert text != null;
+
+        log.debug("Echoing: {}", text);
+
+        session.send(new EchoMessage(text)).join();
+    }
+
+    public void openShell() throws Exception {
+        log.debug("Opening remote shell");
+
+        Message resp = session.request(new OpenShellMessage());
+
+        //
+        // TODO: Need some context from the response
+        //
+
+        // log.debug("Response: {}", resp);
+    }
+
+    public void closeShell() throws Exception {
+        log.debug("Closing remote shell");
+
+        Message resp = session.request(new CloseShellMessage());
+
+        //
+        // TODO: Need some context from the response
+        //
+
+        // log.debug("Response: {}", resp);
+    }
+
+    private Object doExecute(final ExecuteMessage msg) throws Exception {
+        assert msg != null;
+
+        ExecuteMessage.Result result = (ExecuteMessage.Result) session.request(msg);
+
+        // Handle result notifications
+        if (result instanceof ExecuteMessage.Notification) {
+            ExecuteMessage.Notification n = (ExecuteMessage.Notification)result;
+
+            throw n.getNotification();
+        }
+
+        // Handle result faults
+        if (result instanceof ExecuteMessage.Fault) {
+            ExecuteMessage.Fault fault = (ExecuteMessage.Fault)result;
+
+            throw new RemoteExecuteException(fault.getCause());
+        }
+
+        Object rv = result.getResult();
+
+        log.debug("Command result: {}", rv);
+
+        return rv;
+    }
+
+    public Object execute(final String line) throws Exception {
+        assert line != null;
+
+        return doExecute(new ExecuteMessage(line));
+    }
+
+    public Object execute(final Object... args) throws Exception {
+        assert args != null;
+
+        return doExecute(new ExecuteMessage(args));
+    }
+
+    public Object execute(final String path, final Object[] args) throws Exception {
+        assert path != null;
+        assert args != null;
+
+        return doExecute(new ExecuteMessage(path, args));
+    }
+
+    public Object execute(final Object[][] cmds) throws Exception {
+        assert cmds != null;
+
+        return doExecute(new ExecuteMessage(cmds));
+    }
+
+    protected void onSessionClosed() {
+        // nothing
+    }
+
+    //
+    // IO Handler
+    //
+
+    private class Handler
+        extends DemuxingIoHandler
+    {
+        public Handler() throws Exception {
+            // Complain if we don't have any handlers
+            if (handlers.isEmpty()) {
+                throw new Error("No message handlers were discovered");
+            }
+
+            for (ClientMessageHandler handler : handlers) {
+                register(handler);
+            }
+        }
+
+        public void register(final MessageHandler handler) {
+            assert handler != null;
+
+            Class<?> type = handler.getType();
+
+            log.debug("Registering handler: {} -> {}", type.getSimpleName(), handler);
+
+            // noinspection unchecked
+            addMessageHandler(type, handler);
+        }
+
+        @Override
+        public void sessionOpened(final IoSession session) throws Exception {
+            assert session != null;
+
+            // Install the session context
+            ClientSessionContext context = ClientSessionContext.BINDER.bind(session, new ClientSessionContext());
+            log.debug("Created session context: {}", context);
+        }
+
+        @Override
+        public void sessionClosed(final IoSession session) throws Exception {
+            assert session != null;
+
+            ClientSessionContext context = ClientSessionContext.BINDER.unbind(session);
+            log.debug("Removed session context: {}", context);
+            onSessionClosed();
+        }
+    }
+}
\ No newline at end of file

Added: servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/remote/client/SpringRshClient.java
URL: http://svn.apache.org/viewvc/servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/remote/client/SpringRshClient.java?rev=699054&view=auto
==============================================================================
--- servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/remote/client/SpringRshClient.java (added)
+++ servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/remote/client/SpringRshClient.java Thu Sep 25 11:58:57 2008
@@ -0,0 +1,294 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.geronimo.gshell.remote.client;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URI;
+import java.util.List;
+
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.LoginContext;
+
+import org.apache.geronimo.gshell.remote.client.auth.RemoteLoginModule;
+import org.apache.geronimo.gshell.remote.client.handler.ClientMessageHandler;
+import org.apache.geronimo.gshell.remote.client.handler.ClientSessionContext;
+import org.apache.geronimo.gshell.remote.client.RemoteExecuteException;
+import org.apache.geronimo.gshell.remote.client.RshClient;
+import org.apache.geronimo.gshell.remote.crypto.CryptoContext;
+import org.apache.geronimo.gshell.remote.jaas.JaasConfigurationHelper;
+import org.apache.geronimo.gshell.remote.jaas.UsernamePasswordCallbackHandler;
+import org.apache.geronimo.gshell.remote.message.CloseShellMessage;
+import org.apache.geronimo.gshell.remote.message.ConnectMessage;
+import org.apache.geronimo.gshell.remote.message.EchoMessage;
+import org.apache.geronimo.gshell.remote.message.ExecuteMessage;
+import org.apache.geronimo.gshell.remote.message.OpenShellMessage;
+import org.apache.geronimo.gshell.whisper.message.Message;
+import org.apache.geronimo.gshell.whisper.message.MessageHandler;
+import org.apache.geronimo.gshell.whisper.transport.Session;
+import org.apache.geronimo.gshell.whisper.transport.Transport;
+import org.apache.geronimo.gshell.whisper.transport.TransportFactory;
+import org.apache.geronimo.gshell.whisper.transport.TransportFactoryLocator;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.handler.demux.DemuxingIoHandler;
+import org.codehaus.plexus.component.annotations.Component;
+import org.codehaus.plexus.component.annotations.Requirement;
+import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
+import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Provides support for the client-side of the remote shell protocol.
+ *
+ * @version $Rev: 638824 $ $Date: 2008-03-19 14:30:40 +0100 (Wed, 19 Mar 2008) $
+ */
+@Component(role=SpringRshClient.class, instantiationStrategy="per-lookup")
+public class SpringRshClient extends RshClient
+    implements Initializable
+{
+    private final Logger log = LoggerFactory.getLogger(getClass());
+
+    @Requirement
+    private CryptoContext crypto;
+
+    @Requirement
+    private TransportFactoryLocator locator;
+
+    private Transport transport;
+
+    private Session session;
+
+    @Requirement(role=ClientMessageHandler.class)
+    private List<ClientMessageHandler> handlers;
+
+    public SpringRshClient() {
+    }
+
+    public SpringRshClient(final CryptoContext crypto, final TransportFactoryLocator locator, final List<ClientMessageHandler> handlers) {
+        this.crypto = crypto;
+        this.locator = locator;
+        this.handlers = handlers;
+    }
+
+    public void initialize() throws InitializationException {
+        new JaasConfigurationHelper("client.login.conf").initialize();
+    }
+
+    public void connect(final URI remote, final URI local) throws Exception {
+        TransportFactory factory = locator.locate(remote);
+
+        transport = factory.connect(remote, local, new Handler());
+        session = transport.getSession();
+
+        log.debug("Connected to: {}", remote);
+    }
+
+    public InputStream getInputStream() {
+        return session.getInputStream();
+    }
+
+    public OutputStream getOutputStream() {
+        return session.getOutputStream();
+    }
+
+    public Transport getTransport() {
+        return transport;
+    }
+
+    public void close() {
+        transport.close();
+    }
+
+    public void login(final String username, final String password) throws Exception {
+        doHandshake();
+        doLogin(username, password);
+    }
+
+    private void doHandshake() throws Exception {
+        log.debug("Handshaking");
+
+        ClientSessionContext context = ClientSessionContext.BINDER.lookup(session.getSession());
+
+        Message response = session.request(new ConnectMessage(crypto.getPublicKey()));
+
+        if (response instanceof ConnectMessage.Result) {
+            ConnectMessage.Result result = (ConnectMessage.Result)response;
+            context.pk = result.getPublicKey();
+        }
+        else {
+            throw new InternalError("Unexpected handshake response: " + response);
+        }
+    }
+
+    private void doLogin(final String username, final String password) throws Exception {
+        log.debug("Logging in: {}", username);
+
+        ClientSessionContext context = ClientSessionContext.BINDER.lookup(session.getSession());
+
+        CallbackHandler callbackHandler = new UsernamePasswordCallbackHandler(username, password);
+        LoginContext loginContext = new LoginContext("RshClient", callbackHandler);
+
+        RemoteLoginModule.setTransport(transport);
+        try {
+            loginContext.login();
+        }
+        finally {
+            RemoteLoginModule.unsetTransport();
+        }
+
+        context.subject = loginContext.getSubject();
+        log.debug("Subject: {}", context.subject);
+    }
+
+    public void echo(final String text) throws Exception {
+        assert text != null;
+
+        log.debug("Echoing: {}", text);
+
+        session.send(new EchoMessage(text)).join();
+    }
+
+    public void openShell() throws Exception {
+        log.debug("Opening remote shell");
+
+        Message resp = session.request(new OpenShellMessage());
+
+        //
+        // TODO: Need some context from the response
+        //
+
+        // log.debug("Response: {}", resp);
+    }
+
+    public void closeShell() throws Exception {
+        log.debug("Closing remote shell");
+
+        Message resp = session.request(new CloseShellMessage());
+
+        //
+        // TODO: Need some context from the response
+        //
+
+        // log.debug("Response: {}", resp);
+    }
+
+    private Object doExecute(final ExecuteMessage msg) throws Exception {
+        assert msg != null;
+
+        ExecuteMessage.Result result = (ExecuteMessage.Result) session.request(msg);
+
+        // Handle result notifications
+        if (result instanceof ExecuteMessage.Notification) {
+            ExecuteMessage.Notification n = (ExecuteMessage.Notification)result;
+
+            throw n.getNotification();
+        }
+
+        // Handle result faults
+        if (result instanceof ExecuteMessage.Fault) {
+            ExecuteMessage.Fault fault = (ExecuteMessage.Fault)result;
+
+            throw new RemoteExecuteException(fault.getCause());
+        }
+
+        Object rv = result.getResult();
+
+        log.debug("Command result: {}", rv);
+
+        return rv;
+    }
+
+    public Object execute(final String line) throws Exception {
+        assert line != null;
+
+        return doExecute(new ExecuteMessage(line));
+    }
+
+    public Object execute(final Object... args) throws Exception {
+        assert args != null;
+
+        return doExecute(new ExecuteMessage(args));
+    }
+
+    public Object execute(final String path, final Object[] args) throws Exception {
+        assert path != null;
+        assert args != null;
+
+        return doExecute(new ExecuteMessage(path, args));
+    }
+
+    public Object execute(final Object[][] cmds) throws Exception {
+        assert cmds != null;
+
+        return doExecute(new ExecuteMessage(cmds));
+    }
+
+    protected void onSessionClosed() {
+        // nothing
+    }
+
+    //
+    // IO Handler
+    //
+
+    private class Handler
+        extends DemuxingIoHandler
+    {
+        public Handler() throws Exception {
+            // Complain if we don't have any handlers
+            if (handlers.isEmpty()) {
+                throw new Error("No message handlers were discovered");
+            }
+
+            for (ClientMessageHandler handler : handlers) {
+                register(handler);
+            }
+        }
+
+        public void register(final MessageHandler handler) {
+            assert handler != null;
+
+            Class<?> type = handler.getType();
+
+            log.debug("Registering handler: {} -> {}", type.getSimpleName(), handler);
+
+            // noinspection unchecked
+            addMessageHandler(type, handler);
+        }
+
+        @Override
+        public void sessionOpened(final IoSession session) throws Exception {
+            assert session != null;
+
+            // Install the session context
+            ClientSessionContext context = ClientSessionContext.BINDER.bind(session, new ClientSessionContext());
+            log.debug("Created session context: {}", context);
+        }
+
+        @Override
+        public void sessionClosed(final IoSession session) throws Exception {
+            assert session != null;
+
+            ClientSessionContext context = ClientSessionContext.BINDER.unbind(session);
+            log.debug("Removed session context: {}", context);
+            onSessionClosed();
+        }
+    }
+}
\ No newline at end of file

Modified: servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/remote/client/SpringRshCommand.java
URL: http://svn.apache.org/viewvc/servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/remote/client/SpringRshCommand.java?rev=699054&r1=699053&r2=699054&view=diff
==============================================================================
--- servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/remote/client/SpringRshCommand.java (original)
+++ servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/java/org/apache/geronimo/gshell/remote/client/SpringRshCommand.java Thu Sep 25 11:58:57 2008
@@ -19,18 +19,27 @@
 import java.net.URI;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.io.FilterInputStream;
+import java.io.InputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.io.IOException;
 
 import jline.Terminal;
 import org.apache.geronimo.gshell.ExitNotification;
+import org.apache.geronimo.gshell.spring.NoCloseInputStream;
 import org.apache.geronimo.gshell.support.OsgiCommandSupport;
 import org.apache.geronimo.gshell.clp.Argument;
 import org.apache.geronimo.gshell.clp.Option;
 import org.apache.geronimo.gshell.command.annotation.CommandComponent;
+import org.apache.geronimo.gshell.command.IO;
 import org.apache.geronimo.gshell.console.PromptReader;
 import org.apache.geronimo.gshell.remote.client.handler.ClientMessageHandler;
 import org.apache.geronimo.gshell.remote.client.proxy.RemoteShellProxy;
 import org.apache.geronimo.gshell.remote.crypto.CryptoContext;
 import org.apache.geronimo.gshell.whisper.transport.TransportFactoryLocator;
+import org.apache.geronimo.gshell.whisper.stream.StreamFeeder;
 
 /**
  * Created by IntelliJ IDEA.
@@ -82,55 +91,74 @@
     protected Object doExecute() throws Exception {
         io.info("Connecting to: {}", remote);
 
-        RshClient client = new RshClient(crypto, locator, handlers);
-        client.initialize();
-        PromptReader prompter = new PromptReader(terminal, io);
-        prompter.initialize();      
-
-        client.connect(remote, local);
-
-        io.info("Connected");
-
-        // If the username/password was not configured via cli, then prompt the user for the values
-        if (username == null || password == null) {
-            if (username == null) {
-                username = prompter.readLine("Username: ");
-            }
+        final NoCloseInputStream ncis = new NoCloseInputStream(this.io.inputStream);
+        final IO io = new IO(ncis, this.io.outputStream, this.io.errorStream);
+        final AtomicBoolean disconnected = new AtomicBoolean(false);
 
-            if (password == null) {
-                password = prompter.readPassword("Password: ");
+        try {
+            SpringRshClient client = new SpringRshClient(crypto, locator, handlers) {
+                protected void onSessionClosed() {
+                    disconnected.set(true);
+                    try {
+                        ncis.close();
+                    } catch (IOException e) {}
+                }
+            };
+            client.initialize();
+            PromptReader prompter = new PromptReader(terminal, io);
+            prompter.initialize();
+
+            client.connect(remote, local);
+
+            this.io.info("Connected");
+
+            // If the username/password was not configured via cli, then prompt the user for the values
+            if (username == null || password == null) {
+                if (username == null) {
+                    username = prompter.readLine("Username: ");
+                }
+
+                if (password == null) {
+                    password = prompter.readPassword("Password: ");
+                }
+
+                //
+                // TODO: Handle null inputs...
+                //
             }
 
-            //
-            // TODO: Handle null inputs...
-            //
-        }
-
-        client.login(username, password);
+            client.login(username, password);
 
-        // client.echo("HELLO");
-        // Thread.sleep(1 * 1000);
+            // client.echo("HELLO");
+            // Thread.sleep(1 * 1000);
 
-        RemoteShellProxy shell = new RemoteShellProxy(client, io, terminal);
+            RemoteShellProxy shell = new RemoteShellProxy(client, io, terminal);
 
-        Object rv = SUCCESS;
+            Object rv = SUCCESS;
 
-        try {
-            shell.run(command.toArray());
-        }
-        catch (ExitNotification n) {
-            // Make sure that we catch this notification, so that our parent shell doesn't exit when the remote shell does
-            rv = n.code;
-        }
+            try {
+                shell.run(command.toArray());
+            }
+            catch (ExitNotification n) {
+                // Make sure that we catch this notification, so that our parent shell doesn't exit when the remote shell does
+                rv = n.code;
+            }
 
-        shell.close();
+            if (!disconnected.get()) {
+                shell.close();
+            }
 
-        io.verbose("Disconnecting");
+            this.io.verbose("Disconnecting");
 
-        client.close();
+            client.close();
 
-        io.verbose("Disconnected");
+            this.io.verbose("Disconnected");
 
-        return rv;
+            return rv;
+        } finally {
+            try {
+                ncis.close();
+            } catch (IOException e) {}
+        }
     }
 }

Modified: servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-remote.xml
URL: http://svn.apache.org/viewvc/servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-remote.xml?rev=699054&r1=699053&r2=699054&view=diff
==============================================================================
--- servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-remote.xml (original)
+++ servicemix/smx4/kernel/trunk/gshell/gshell-core/src/main/resources/META-INF/spring/gshell-remote.xml Thu Sep 25 11:58:57 2008
@@ -32,7 +32,7 @@
   http://servicemix.apache.org/jaas
   http://servicemix.apache.org/schema/servicemix-jaas.xsd">
 
-    <bean id="rshServer" class="org.apache.geronimo.gshell.remote.server.RshServer">
+    <bean id="rshServer" class="org.apache.geronimo.gshell.remote.server.RshServer" destroy-method="close">
         <constructor-arg ref="timeoutManager" />
         <constructor-arg ref="transportFactoryLocator" />
         <constructor-arg>

Modified: servicemix/smx4/kernel/trunk/gshell/gshell-osgi/src/main/java/org/apache/geronimo/gshell/osgi/Shutdown.java
URL: http://svn.apache.org/viewvc/servicemix/smx4/kernel/trunk/gshell/gshell-osgi/src/main/java/org/apache/geronimo/gshell/osgi/Shutdown.java?rev=699054&r1=699053&r2=699054&view=diff
==============================================================================
--- servicemix/smx4/kernel/trunk/gshell/gshell-osgi/src/main/java/org/apache/geronimo/gshell/osgi/Shutdown.java (original)
+++ servicemix/smx4/kernel/trunk/gshell/gshell-osgi/src/main/java/org/apache/geronimo/gshell/osgi/Shutdown.java Thu Sep 25 11:58:57 2008
@@ -21,18 +21,22 @@
 import org.osgi.framework.Bundle;
 
 /**
- * Created by IntelliJ IDEA.
- * User: gnodet
- * Date: Oct 3, 2007
- * Time: 1:59:04 PM
- * To change this template use File | Settings | File Templates.
+ * Command to shut down ServiceMix Kernel
  */
 @CommandComponent(id="osgi:shutdown", description="Shutdown")
 public class Shutdown extends OsgiCommandSupport {
 
     protected Object doExecute() throws Exception {
-        Bundle bundle = getBundleContext().getBundle(0);
-        bundle.stop();
+        new Thread() {
+            public void run() {
+                try {
+                    Bundle bundle = getBundleContext().getBundle(0);
+                    bundle.stop();
+                } catch (Exception e) {
+                    log.error("Error when shutting down ServiceMix Kernel", e);
+                }
+            }
+        }.start();
         return SUCCESS;
     }