All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.hidetake.groovy.ssh.connection.Connection.groovy Maven / Gradle / Ivy

There is a newer version: 2.11.2
Show newest version
package org.hidetake.groovy.ssh.connection

import com.jcraft.jsch.*
import groovy.util.logging.Slf4j
import org.hidetake.groovy.ssh.core.Remote
import org.hidetake.groovy.ssh.session.BackgroundCommandException
import org.hidetake.groovy.ssh.session.BadExitStatusException
import org.hidetake.groovy.ssh.session.forwarding.LocalPortForwardSettings
import org.hidetake.groovy.ssh.session.forwarding.RemotePortForwardSettings

/**
 * A SSH connection.
 *
 * @author Hidetake Iwata
 */
@Slf4j
class Connection {
    final Remote remote

    private final Session session
    private final List channels = []
    private final List callbackForClosedChannels = []

    def Connection(Remote remote1, Session session1) {
        remote = remote1
        session = session1
        assert remote
        assert session
    }

    /**
     * Create an execution channel.
     *
     * @return a channel
     */
    ChannelExec createExecutionChannel() {
        def channel = session.openChannel('exec') as ChannelExec
        channels.add(channel)
        channel
    }

    /**
     * Create a shell channel.
     *
     * @param operationSettings
     * @return a channel
     */
    ChannelShell createShellChannel() {
        def channel = session.openChannel('shell') as ChannelShell
        channels.add(channel)
        channel
    }

    /**
     * Create a SFTP channel.
     *
     * @return a channel
     */
    ChannelSftp createSftpChannel() {
        def channel = session.openChannel('sftp') as ChannelSftp
        channels.add(channel)
        channel
    }

    /**
     * Set up local port forwarding.
     *
     * @param settings
     * @return local port
     */
    int forwardLocalPort(LocalPortForwardSettings settings) {
        session.setPortForwardingL(settings.bind, settings.port, settings.host, settings.hostPort)
    }

    /**
     * Set up remote port forwarding.
     *
     * @param settings
     */
    void forwardRemotePort(RemotePortForwardSettings settings) {
        session.setPortForwardingR(settings.bind, settings.port, settings.host, settings.hostPort)
    }

    /**
     * Register a closure called when the channel is closed.
     *
     * @param channel the channel
     * @param closure callback closure
     */
    void whenClosed(Channel channel, Closure closure) {
        boolean executed = false
        callbackForClosedChannels.add { ->
            if (!executed && channel.closed) {
                executed = true
                closure(channel)
            }
        }
    }

    /**
     * Execute registered closures.
     * This method throws a {@link BackgroundCommandException} if any closure returns an exception.
     *
     * @see #whenClosed(com.jcraft.jsch.Channel, groovy.lang.Closure)
     */
    void executeCallbackForClosedChannels() {
        List exceptions = []
        callbackForClosedChannels.each { callback ->
            try {
                callback.call()
            } catch (Exception e) {
                exceptions.add(e)
                if (e instanceof BadExitStatusException) {
                    log.error("${e.class.name}: ${e.localizedMessage}")
                } else {
                    log.error("Error occurred on $remote", e)
                }
            }
        }
        if (!exceptions.empty) {
            throw new BackgroundCommandException(exceptions)
        }
    }

    /**
     * Return if any channel is pending.
     *
     * @return true if at least one is pending
     */
    boolean isAnyPending() {
        channels.any { channel -> channel.connected && !channel.closed }
    }

    /**
     * Cleanup the connection and all channels.
     */
    void close() {
        try {
            channels*.disconnect()
            channels.clear()
        } finally {
            session.disconnect()
            log.info("Disconnected from $remote")
        }
    }

    @Override
    String toString() {
        "Connection[$remote]"
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy