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

org.echocat.jomon.net.ssh.jsch.JschUtils Maven / Gradle / Ivy

/*****************************************************************************************
 * *** BEGIN LICENSE BLOCK *****
 *
 * Version: MPL 2.0
 *
 * echocat Jomon, Copyright (c) 2012-2013 echocat
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * *** END LICENSE BLOCK *****
 ****************************************************************************************/

package org.echocat.jomon.net.ssh.jsch;

import com.jcraft.jsch.*;
import com.jcraft.jsch.NotifyingIO.EventConsumer;
import org.echocat.jomon.net.ssh.SshConnectionException;
import org.echocat.jomon.net.ssh.SshSystemException;

import javax.annotation.Nonnull;
import java.lang.reflect.Field;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import static java.lang.Class.forName;
import static org.echocat.jomon.runtime.reflection.ClassUtils.getFieldOf;

public class JschUtils {

    @Nonnull
    private static final Map, String> TYPE_TO_NAME = createTypeToName();
    @Nonnull
    private static final Field IO_FIELD = getFieldOf(Channel.class, IO.class, "io", false);

    private static Map, String> createTypeToName() {
        final Map, String> typeToName = new HashMap<>();
        addIfPresent(typeToName, "com.jcraft.jsch.ChannelSession", "session");
        addIfPresent(typeToName, "com.jcraft.jsch.ChannelShell", "shell");
        addIfPresent(typeToName, "com.jcraft.jsch.ChannelExec", "exec");
        addIfPresent(typeToName, "com.jcraft.jsch.ChannelX11", "x11");
        addIfPresent(typeToName, "com.jcraft.jsch.ChannelAgentForwarding", "[email protected]");
        addIfPresent(typeToName, "com.jcraft.jsch.ChannelDirectTCPIP", "direct-tcpip");
        addIfPresent(typeToName, "com.jcraft.jsch.ChannelForwardedTCPIP", "forwarded-tcpip");
        addIfPresent(typeToName, "com.jcraft.jsch.ChannelSftp", "sftp");
        addIfPresent(typeToName, "com.jcraft.jsch.ChannelSubsystem", "subsystem");
        return Collections.unmodifiableMap(typeToName);
    }

    private static void addIfPresent(@Nonnull Map, String> typeToName, @Nonnull String className, @Nonnull String typeName) {
        try {
            // noinspection unchecked
            typeToName.put((Class) forName(className), typeName);
        } catch (ClassNotFoundException ignored) {}
    }

    @Nonnull
    public static  T open(@Nonnull Session session, @Nonnull Class type) {
        final String name = TYPE_TO_NAME.get(type);
        if (name == null) {
            throw new IllegalArgumentException("Type " + type.getName() + " is unknown.");
        }
        return open(session, type, name);
    }

    @Nonnull
    public static  T open(@Nonnull Session session, @Nonnull Class type, @Nonnull String typeName) {
        if (!session.isConnected()) {
            throw new SshConnectionException("Not connected.");
        }
        final Channel channel;
        try {
            channel = session.openChannel(typeName);
        } catch (JSchException e) {
            throw new SshSystemException("Could not open channel '" + typeName + "'.", e);
        }
        if (!type.isInstance(channel)) {
            throw new SshSystemException("Created channel " + channel + "  is not of type " + type.getName() + ".");
        }
        return type.cast(channel);
    }

    public static void register(@Nonnull EventConsumer consumer, @Nonnull Channel on) {
        // noinspection SynchronizationOnLocalVariableOrMethodParameter
        synchronized (on) {
            try {
                final IO io = (IO) IO_FIELD.get(on);
                final NotifyingIO notifyingIO;
                if (io instanceof NotifyingIO) {
                    notifyingIO = (NotifyingIO) io;
                } else {
                    notifyingIO = new NotifyingIO(io);
                    IO_FIELD.set(on, notifyingIO);
                }
                notifyingIO.setEventConsumer(consumer);
            } catch (Exception e) {
                throw new RuntimeException("Could not set the io field of '" + on + "'.", e);
            }
        }
    }

    private JschUtils() {}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy