Package org.apache.karaf.eik.core.shell

Source Code of org.apache.karaf.eik.core.shell.KarafSshShellConnection

/*
* 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.karaf.eik.core.shell;

import org.apache.karaf.eik.core.internal.KarafCorePluginActivator;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.sshd.ClientChannel;
import org.apache.sshd.ClientSession;
import org.apache.sshd.SshClient;
import org.apache.sshd.client.future.AuthFuture;
import org.apache.sshd.client.future.ConnectFuture;
import org.apache.sshd.common.util.NoCloseInputStream;
import org.apache.sshd.common.util.NoCloseOutputStream;
import org.fusesource.jansi.AnsiConsole;

public class KarafSshShellConnection implements KarafRemoteShellConnection {

    public static final class Credentials {

        private final String password;

        private final String username;

        public Credentials(final String username, final String password) {
            this.username = username;
            this.password = password;
        }

        @Override
        public boolean equals(final Object obj) {
            if (this == obj) {
                return true;
            }

            if (obj == null) {
                return false;
            }

            if (!(obj instanceof Credentials)) {
                return false;
            }

            final Credentials other = (Credentials) obj;
            if (password == null) {
                if (other.password != null) {
                    return false;
                }
            } else if (!password.equals(other.password)) {
                return false;
            }

            if (username == null) {
                if (other.username != null) {
                    return false;
                }
            } else if (!username.equals(other.username)) {
                return false;
            }

            return true;
        }

        public String getPassword() {
            return password;
        }

        public String getUsername() {
            return username;
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + (password == null ? 0 : password.hashCode());
            result = prime * result + (username == null ? 0 : username.hashCode());
            return result;
        }
    }

    private ClientChannel clientChannel;

    private ClientSession clientSession;

    private final AtomicBoolean connected = new AtomicBoolean();

    private int connectionStatus;

    private final KarafSshConnectionUrl connectionUrl;

    private final Credentials credentials;

    private final OutputStream errorStream;

    private volatile Throwable exception;

    private final InputStream inputStream;

    private final OutputStream outputStream;

    private SshClient sshClient;

    /**
     * Creates a remote shell connection to a Karaf instance using the SSH
     * protocol
     *
     * @param connectionUrl
     *            the coordinates used to establish the connection
     * @param credentials
     *            the username and password used to authenticate when connection
     * @param inputStream
     *            the {@link InputStream} used to interact with the remote
     *            system
     * @param outputStream
     *            the {@link OutputStream} used to receive data from
     *            {@code stdout} of the remote system
     * @param errorStream
     *            the {@link OutputStream} used to receive data from
     *            {@code stderr} of the remote system
     */
    public KarafSshShellConnection(
            final KarafSshConnectionUrl connectionUrl,
            final Credentials credentials,
            final InputStream inputStream,
            final OutputStream outputStream,
            final OutputStream errorStream)
    {

        this.connectionUrl = connectionUrl;
        this.credentials = credentials;

        this.inputStream = inputStream;
        this.outputStream = outputStream;
        this.errorStream = errorStream;

        this.exception = null;

        this.sshClient = SshClient.setUpDefaultClient();
    }

    @Override
    public void connect() throws IOException {
        sshClient.start();

        try {
            final ConnectFuture connectFuture = sshClient.connect(connectionUrl.getHost(), connectionUrl.getPort());
            connectFuture.await(15 * 1000);

            clientSession = connectFuture.getSession();

            final AuthFuture authFuture = clientSession.authPassword(credentials.getUsername(), credentials.getPassword());
            authFuture.await(15 * 1000);

            if (!authFuture.isSuccess()) {
                exception = authFuture.getException();

                try {
                    disconnect();
                } catch (final IOException e) {
                    KarafCorePluginActivator.getLogger().warn("Error while disconnecting after authenticate failure", e);
                }

                throw new IOException(exception);
            }

            clientChannel = clientSession.createChannel(ClientChannel.CHANNEL_SHELL);

            clientChannel.setIn(new NoCloseInputStream(inputStream));
            clientChannel.setOut(AnsiConsole.wrapOutputStream(new NoCloseOutputStream(outputStream)));
            clientChannel.setErr(AnsiConsole.wrapOutputStream(new NoCloseOutputStream(errorStream)));

            connected.set(true);

            clientChannel.open();
            connectionStatus = clientChannel.waitFor(ClientChannel.CLOSED, 15 * 1000);
        } catch (final Exception e) {
            throw new IOException(e);
        }
    }

    @Override
    public void disconnect() throws IOException {
        try {
            if (clientChannel != null) {
                clientChannel.close(true).await();
            }

            if (clientSession != null) {
                clientSession.close(true).await();
            }
        } catch (final Exception e) {
            throw new IOException(e);
        } finally {
            clientChannel = null;
            clientSession = null;

            connected.set(false);
        }
    }

    public int getConnectionStatus() {
        return connectionStatus;
    }

    public Throwable getException() {
        return exception;
    }

    @Override
    public boolean isConnected() {
        return connected.get();
    }

    public void setSshClient(final SshClient sshClient) {
        this.sshClient = sshClient;
    }

}
TOP

Related Classes of org.apache.karaf.eik.core.shell.KarafSshShellConnection

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.