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

net.oneandone.sushi.fs.ssh.SshRoot Maven / Gradle / Ivy

/**
 * Copyright 1&1 Internet AG, https://github.com/1and1/
 *
 * Licensed 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 net.oneandone.sushi.fs.ssh;

import com.jcraft.jsch.*;
import net.oneandone.sushi.fs.OnShutdown;
import net.oneandone.sushi.fs.Root;
import net.oneandone.sushi.io.MultiOutputStream;
import net.oneandone.sushi.launcher.ExitCode;

import java.io.ByteArrayOutputStream;
import java.io.OutputStream;

// TODO: dump UserInfo interface?
public class SshRoot implements Root, Runnable {
    private final SshFilesystem filesystem;
    private final String user;

    private final String host;
    private final int port;
    private final Session session;

    // created on demand because it's only needed for nodes, not for "exec" stuff
    private ChannelSftp sftp;

    public SshRoot(SshFilesystem filesystem, String host, String user, int timeout) throws JSchException {
        this(filesystem, host, 22, user, timeout);
    }

    public SshRoot(SshFilesystem filesystem, String host, int port, String user, int timeout)
    throws JSchException {
        this.filesystem = filesystem;
        this.user = user;
        this.host = host;
        this.port = port;
        this.session = filesystem.getJSch().getSession(user, host, port);
        this.session.connect(timeout);
        this.sftp = null;
        OnShutdown.get().onShutdown(this);
    }

    //-- Root interface

    public SshFilesystem getFilesystem() {
        return filesystem;
    }

    public String getId() {
        return "//" + session.getUserName() + "@" + session.getHost() + "/";
    }

    public SshNode node(String path, String encodedQuery) {
        if (encodedQuery != null) {
            throw new IllegalArgumentException(encodedQuery);
        }
        return new SshNode(this, path);
    }

    @Override
    public boolean equals(Object obj) {
        SshRoot root;

        if (obj instanceof SshRoot) {
            root = (SshRoot) obj;
            return getId().equals(root.getId());
        }
        return false;
    }

    @Override
    public int hashCode() {
        return getId().hashCode();
    }

    @Override
    public String toString() {
        return "SshNode host=" + host + ", user=" + user;
    }

    //--

    private int allocated = 0;

    public synchronized int getAllocated() {
        return allocated;
    }

    public synchronized ChannelSftp allocateChannelSftp() throws JSchException {
        ChannelSftp result;

        if (sftp != null) {
            result = sftp;
            sftp = null;
        } else {
            result = (ChannelSftp) session.openChannel("sftp");
            result.connect();
        }
        allocated++;
        return result;
    }

    public synchronized void freeChannelSftp(ChannelSftp free) {
        if (sftp == null) {
            sftp = free;
        } else {
            free.disconnect();
        }
        allocated--;
    }

    public ChannelExec createChannelExec() throws JSchException {
        return (ChannelExec) session.openChannel("exec");
    }

    public void close() {
        session.disconnect();
    }

    public Process start(boolean tty, String ... command) throws JSchException {
        return start(tty, MultiOutputStream.createNullStream(), command);
    }

    public Process start(boolean tty, OutputStream out, String ... command) throws JSchException {
        return Process.start(this, tty, out, command);
    }

    //-- exec methods
    //    I'd like to align this with Program execution, but I cannot set a working directory in Ssh Execution

    public String exec(String ... command) throws JSchException, ExitCode {
        return exec(true, command);
    }

    public String exec(boolean tty, String ... command) throws JSchException, ExitCode {
        ByteArrayOutputStream out;

        out = new ByteArrayOutputStream();
        try {
            start(tty, out, command).waitFor();
        } catch (ExitCode e) {
            throw new ExitCode(e.launcher, e.code, filesystem.getWorld().getSettings().string(out));
        }
        return filesystem.getWorld().getSettings().string(out);
    }

    //--

    public String getUser() {
        return user;
    }

    public String getHost() {
        return host;
    }

    // executes on shutdown
    public void run() {
        close();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy