[JAVA/JsCh] Un client SSH pour Java

La mise en place d’un client SSH robuste pour Java n’est pas aussi simple qu’il n’y parait.

Il existe bon nombre d’API, mais peu de comparatifs. Qui plus est, les documentations sont, de manière générale, peu explicites.

Je vais vous fournir ici un client SSH prêt à être utilisé dans tout type de projet. Il est basé sur l’API JsCh (qui à mon avis est la plus rapide à prendre en main) ainsi qu’une classe utilitaire de Apache permettant d’implémenter l’échange de fichiers avec le protocole SCP (une petite présentation ici).

Ci-dessous donc :

  • la classe SSHClient qui contient  l’essentiel du code fonctionnel pour se connecter à un hôte SSH et dialoguer (envoi de commandes…)
  • la classe Apache ajoutant la couche Scp pour l’échange de fichiers

Il ne vous reste plus qu’à modifier, à l’intérieur de la classe SSHClient, les logins pour accéder à la machine distante.

Ce code est bien entendu libre et peut être modifié à volonté.

SSHClient.java

package com;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.UserInfo;

public class SSHClient {

    /** Channel modes */
    public static final String  EXEC_MODE               = "exec";

    public static final String  SHELL_MODE              = "shell";

    public static final String  SFTP_MODE               = "sftp";

    /** Authentication */
    private static String       USER;

    private static String       PWD;

    private static String       HOST;

    /** Utils */
    private String              CMD_INVITE;

    private PipedInputStream    fromServer;

    private OutputStream        toServer;

    private Channel             channel;

    private Session             session;

    private static final String TERMINATOR              = "zDonez";

    private String              lastCommand             = "";

    private Pattern             alphaNumeric            = Pattern
                                                            .compile("([^a-zA-z0-9])");

    private int                 nbChannel               = 0;

    private String              previousMode;

    private int                 SERVER_RESPONSE_TIMEOUT = 1500;

    /** Low-level layer to provide ssh functions */
    private Scp                 scp;

    /** Shell */
    private JSch                shell;

    public SSHClient() throws Exception {
        shell = new JSch();
        USER = "test";
        PWD = "test";
        HOST = "test";
        CMD_INVITE = HOST + ":" + USER + "#";
        initSession();
    }

    /**
     * Init SSH session
     * @throws Exception 
     * @throws JSchException
     */
    private void initSession() throws Exception {
        try {
            session = shell.getSession(USER, HOST, 22);
            MyUserInfo ui = new MyUserInfo();
            ui.setPassword(PWD);
            session.setUserInfo(ui);

            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);

            session.connect();
            // session.connect(30000); // making a connection with timeout.
            scp = new Scp(session);
        } catch (JSchException e) {
            e.printStackTrace();
            LOGGER.error(e);
            throw new Exception(e.getLocalizedMessage());
        }
    }

    /**
     * Connects to remote machine
     * @param mode Type of channel to open : can be EXEC_MODE, SHELL_MODE, SFTP_MODE
     * @throws Exception 
     * @throws JSchException
     * @throws IOException
     * @throws InterruptedException
     */
    private void connect(String mode) throws Exception {

        if (!isConnected()) {
            try {
                channel = session.openChannel(mode);
                previousMode = mode;
                // If Shell mode, customize I/O streams to get response
                if (mode.equals(SHELL_MODE)) {
                    initShellMode();
                    channel.connect();
                }
            } catch (Exception e) {
                e.printStackTrace();
                LOGGER.error(e);
                throw new Exception(e.getLocalizedMessage());
            }
        } else {
            // To avoid 10 files upload limitation in session
            if (nbChannel == 9) {
                disconnect();
                nbChannel = 0;
                connect(mode);
            }
            // Change channel
            if (!previousMode.equals(mode)) {
                previousMode = mode;
                channel.disconnect();
                connect(mode);
            }
            nbChannel++;
        }
    }

    /**
     * Init shell mode
     * @throws IOException
     */
    private void initShellMode() throws IOException {
        PipedOutputStream po = new PipedOutputStream();
        fromServer = new PipedInputStream(po);
        channel.setOutputStream(po);

        toServer = new PipedOutputStream();
        PipedInputStream pi = new PipedInputStream((PipedOutputStream) toServer);
        channel.setInputStream(pi);
    }

    /**
     * Check if client is connected
     * @return YES or NO
     */
    public boolean isConnected() {
        return (channel != null && channel.isConnected());
    }

    /**
     * Disconnect channel and session
     */
    public void disconnect() {
        if (isConnected()) {
            channel.disconnect();
            session.disconnect();
        }
    }

    /**
     * Disconnect client and open new session
     * @throws Exception 
     */
    public void reconnect() throws Exception {
        disconnect();
        initSession();
    }

    /**
     * Send simple SHELL command
     * @param command
     * @return server response
     * @throws Exception 
     * @throws IOException
     * @throws InterruptedException
     */
    public String sendShell(String command) throws Exception {
        connect(SHELL_MODE);
        lastCommand = command;
        command += "; echo \"" + TERMINATOR + "\" \n";
        try {
            toServer.write(command.getBytes());
            // To ensure server answer reception
            // and manage a communication time out.
            try {
                Thread.sleep(SERVER_RESPONSE_TIMEOUT);
            } catch (InterruptedException e) {
            }
        } catch (IOException e) {
            e.printStackTrace();
            LOGGER.error(e);
            throw new Exception(e.getLocalizedMessage());
        }
        return getServerResponse();
    }

    /**
     * Retrieve server response to SHELL command
     * @return the response
     * @throws Exception 
     * @throws IOException
     * @throws InterruptedException
     */
    private String getServerResponse() throws Exception {
        StringBuffer builder = new StringBuffer();
        String result = null;
        try {
            int count = 0;
            String line = "";

            BufferedReader reader = new BufferedReader(new InputStreamReader(
                fromServer));
            if (reader.ready()) {
                for (int i = 0; true; i++) {
                    try {
                        line = reader.readLine();
                    } catch (IOException e) {
                        LOGGER.warn("Communication seems to be closed...");
                        break;
                    }
                    builder.append(line).append("\n");
                    if (line.indexOf(TERMINATOR) != -1 && (++count > 1)) {
                        break;
                    }
                }
                result = builder.toString();
                int beginIndex = result.indexOf(TERMINATOR + "\"")
                    + ((TERMINATOR + "\"").length());
                result = result.substring(beginIndex);
                result = result.replaceAll(escape(TERMINATOR), "").trim();
                System.out.println("Command : " + lastCommand + " -> Result : "
                    + result);
                return result;
            } else {
                throw new Exception("Server did not answer in the time ("
                    + SERVER_RESPONSE_TIMEOUT + "ms) to command ("
                    + lastCommand + ")");
            }
        } catch (IOException e) {
            e.printStackTrace();
            LOGGER.error(e);
            throw new Exception(e.getLocalizedMessage());
        }
    }

    private String escape(String subjectString) {
        return alphaNumeric.matcher(subjectString).replaceAll("\\\\$1");
    }

    /**
     * Execute remote script
     * @param scriptPath
     * @throws Exception
     */
    public String executeScript(String scriptPath, String[] params)
        throws Exception {
        String commandLine = scriptPath;
        for (String p : params) {
            commandLine += " " + p;
        }
        return sendShell(commandLine);
    }

    /**
     * Send a file on server (implementation of exec 'scp -t rfile' command)
     * @param localFilePath
     * @param remoteFilePath
     * @throws Exception
     */
    public void sendFile(String localFilePath, String remoteFilePath)
        throws Exception {
        String remoteTargetDir = remoteFilePath.substring(0, remoteFilePath
            .lastIndexOf("/") + 1);
        String remoteTargetName = remoteFilePath.substring(remoteTargetDir
            .length());
        if (nbChannel == 9) {
            nbChannel = 0;
            reconnect();
        }
        nbChannel++;
        scp.put(localFilePath, remoteTargetDir, remoteTargetName, "0777");
    }

    /**
     * Get files 
     * @param remotePath
     * @param localDestinationPath
     * @throws Exception 
     * @throws IOException 
     */
    public List getResultsFiles(String remotePath,
        String localDestinationPath) throws Exception {
        List filesPaths = new ArrayList();
        // To ensure well connection
        reconnect();
        // List files
        String list = sendShell("ls " + remotePath);
        if (list != null) {
            if (list.indexOf(CMD_INVITE) != -1) {
                list = list.substring(list.indexOf(CMD_INVITE)
                    + CMD_INVITE.length());
            }
            if (list.indexOf("not found") != -1) {
                throw new Exception(
                    "No output files!");
            }
            List files = getFilesList(list);
            if (files.size() > 0) {
                File tmp = null;
                for (String f : files) {
                    tmp = new File(localDestinationPath, f);
                    if (tmp.exists()) {
                        tmp.delete();
                    }
                    if (nbChannel == 9) {
                        nbChannel = 0;
                        reconnect();
                    }
                    nbChannel++;
                    String absPath = tmp.getAbsolutePath();
                    filesPaths.add(absPath);
                    scp.get(remotePath + f, absPath);
                }
                return filesPaths;
            } else {
                throw new Exception(
                    "No output files!");
            }
        } else {
            throw new Exception(
                "Impossible to retreive files list!");
        }
    }

    /**
     * Compute file list received from server ("ls" command) to a list of files
     * @param lsResult
     * @return
     */
    private List getFilesList(String lsResult) {
        List files = new ArrayList();
        String[] tabl = lsResult.split("\\n");
        for (String s : tabl) {
            s = s.trim();
            if (!"".equals(s)) {
                if (s.indexOf(" ") == -1) {
                    files.add(s);
                } else {
                    String[] tabl2 = s.split(" ");
                    for (String s2 : tabl2) {
                        s2 = s2.trim();
                        if (!"".equals(s2)) {
                            files.add(s2);
                        }
                    }
                }
            }
        }
        return files;
    }

    /**
     * Move command shell to specified directory
     * @param path
     * @throws Exception
     */
    public void moveToDir(String path) throws Exception {
        sendShell("cd " + path);
    }

    /**
     * Local class that implements logging credentials
     */
    private static class MyUserInfo implements UserInfo {

        private String password;

        public void setPassword(String password) {
            this.password = password;

        }

        public String getPassphrase() {
            return null;
        }

        public String getPassword() {
            return password;
        }

        public boolean promptPassword(String arg0) {
            return true;
        }

        public boolean promptPassphrase(String arg0) {
            return true;
        }

        public boolean promptYesNo(String arg0) {
            return true;
        }

        public void showMessage(String arg0) {
            System.out.println(arg0);
        }
    }
}

SCP.java

/*
 *  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 com;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.apache.log4j.Logger;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;

/**
 * This class is using the scp client to transfer data and information for the repository. 
 * 

* It is based on the SCPClient from the ganymed ssh library from Christian Plattner, * released under a BSD style license. *

* To minimize the dependency to the ssh library and because we needed some additional * functionality, we decided to copy'n'paste the single class rather than to inherit or * delegate it somehow. *

* Nevertheless credit should go to the original author. */ public class Scp { private static final int MODE_LENGTH = 4; private static final int SEND_FILE_BUFFER_LENGTH = 40000; private static final int SEND_BYTES_BUFFER_LENGTH = 512; private static final int MIN_TLINE_LENGTH = 8; private static final int CLINE_SPACE_INDEX2 = 5; private static final int CLINE_SPACE_INDEX1 = 4; private static final int MIN_C_LINE_LENGTH = 8; private static final int DEFAULT_LINE_BUFFER_LENGTH = 30; private static final int BUFFER_SIZE = 64 * 1024; /* * Maximum length authorized for scp lines. * This is a random limit - if your path names are longer, then adjust it. */ private static final int MAX_SCP_LINE_LENGTH = 8192; private Session session; public class FileInfo { private String filename; private long length; private long lastModified; /** * @param filename * The filename to set. */ public void setFilename(String filename) { this.filename = filename; } /** * @return Returns the filename. */ public String getFilename() { return filename; } /** * @param length * The length to set. */ public void setLength(long length) { this.length = length; } /** * @return Returns the length. */ public long getLength() { return length; } /** * @param lastModified * The lastModified to set. */ public void setLastModified(long lastModified) { this.lastModified = lastModified; } /** * @return Returns the lastModified. */ public long getLastModified() { return lastModified; } } public Scp(Session session) { if (session == null) { throw new IllegalArgumentException("Cannot accept null argument!"); } this.session = session; } private void readResponse(InputStream is) throws IOException, Exception { if (is.available() > 0) { int c = is.read(); if (c == 0) { return; } if (c == -1) { throw new Exception("Remote scp terminated unexpectedly."); } if ((c != 1) && (c != 2)) { throw new Exception("Remote scp sent illegal error code."); } if (c == 2) { throw new Exception("Remote scp terminated with error."); } String err = receiveLine(is); throw new Exception("Remote scp terminated with error (" + err + ")."); } } private String receiveLine(InputStream is) throws IOException, Exception { StringBuffer sb = new StringBuffer(DEFAULT_LINE_BUFFER_LENGTH); while (true) { if (sb.length() > MAX_SCP_LINE_LENGTH) { throw new Exception("Remote scp sent a too long line"); } int c = is.read(); if (c < 0) { throw new Exception("Remote scp terminated unexpectedly."); } if (c == '\n') { break; } sb.append((char) c); } return sb.toString(); } private void parseCLine(String line, FileInfo fileInfo) throws Exception { /* Minimum line: "xxxx y z" ---> 8 chars */ long len; if (line.length() < MIN_C_LINE_LENGTH) { throw new Exception( "Malformed C line sent by remote SCP binary, line too short."); } if ((line.charAt(CLINE_SPACE_INDEX1) != ' ') || (line.charAt(CLINE_SPACE_INDEX2) == ' ')) { throw new Exception( "Malformed C line sent by remote SCP binary."); } int lengthNameSep = line.indexOf(' ', CLINE_SPACE_INDEX2); if (lengthNameSep == -1) { throw new Exception( "Malformed C line sent by remote SCP binary."); } String lengthSubstring = line.substring(CLINE_SPACE_INDEX2, lengthNameSep); String nameSubstring = line.substring(lengthNameSep + 1); if ((lengthSubstring.length() <= 0) || (nameSubstring.length() <= 0)) { throw new Exception( "Malformed C line sent by remote SCP binary."); } if ((CLINE_SPACE_INDEX2 + 1 + lengthSubstring.length() + nameSubstring .length()) != line.length()) { throw new Exception( "Malformed C line sent by remote SCP binary."); } try { len = Long.parseLong(lengthSubstring); } catch (NumberFormatException e) { throw new Exception( "Malformed C line sent by remote SCP binary, cannot parse file length."); } if (len < 0) { throw new Exception( "Malformed C line sent by remote SCP binary, illegal file length."); } fileInfo.setLength(len); fileInfo.setFilename(nameSubstring); } private void parseTLine(String line, FileInfo fileInfo) throws Exception { /* Minimum line: "0 0 0 0" ---> 8 chars */ long modtime; long firstMsec; long atime; long secondMsec; if (line.length() < MIN_TLINE_LENGTH) { throw new Exception( "Malformed T line sent by remote SCP binary, line too short."); } int firstMsecBegin = line.indexOf(" ") + 1; if (firstMsecBegin == 0 || firstMsecBegin >= line.length()) { throw new Exception( "Malformed T line sent by remote SCP binary, line not enough data."); } int atimeBegin = line.indexOf(" ", firstMsecBegin + 1) + 1; if (atimeBegin == 0 || atimeBegin >= line.length()) { throw new Exception( "Malformed T line sent by remote SCP binary, line not enough data."); } int secondMsecBegin = line.indexOf(" ", atimeBegin + 1) + 1; if (secondMsecBegin == 0 || secondMsecBegin >= line.length()) { throw new Exception( "Malformed T line sent by remote SCP binary, line not enough data."); } try { modtime = Long.parseLong(line.substring(0, firstMsecBegin - 1)); firstMsec = Long.parseLong(line.substring(firstMsecBegin, atimeBegin - 1)); atime = Long.parseLong(line.substring(atimeBegin, secondMsecBegin - 1)); secondMsec = Long.parseLong(line.substring(secondMsecBegin)); } catch (NumberFormatException e) { LOGGER.error(e); throw new Exception( "Malformed C line sent by remote SCP binary, cannot parse file length."); } if (modtime < 0 || firstMsec < 0 || atime < 0 || secondMsec < 0) { throw new Exception( "Malformed C line sent by remote SCP binary, illegal file length."); } fileInfo.setLastModified(modtime); } private void sendFile(Channel channel, String localFile, String remoteName, String mode) throws IOException, Exception { byte[] buffer = new byte[BUFFER_SIZE]; OutputStream os = new BufferedOutputStream(channel.getOutputStream(), SEND_FILE_BUFFER_LENGTH); InputStream is = new BufferedInputStream(channel.getInputStream(), SEND_BYTES_BUFFER_LENGTH); try { if (channel.isConnected()) { channel.start(); } else { channel.connect(); } } catch (JSchException e1) { throw (IOException) new IOException("Channel connection problems") .initCause(e1); } readResponse(is); File f = new File(localFile); long remain = f.length(); String cMode = mode; if (cMode == null) { cMode = "0600"; } String cline = "C" + cMode + " " + remain + " " + remoteName + "\n"; os.write(cline.getBytes()); os.flush(); readResponse(is); FileInputStream fis = null; try { fis = new FileInputStream(f); while (remain > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { } int trans; if (remain > buffer.length) { trans = buffer.length; } else { trans = (int) remain; } if (fis.read(buffer, 0, trans) != trans) { throw new IOException("Cannot read enough from local file " + localFile); } os.write(buffer, 0, trans); remain -= trans; } fis.close(); } catch (Exception e) { if (fis != null) { fis.close(); } LOGGER.error(e); throw new Exception(e); } os.write(0); os.flush(); readResponse(is); os.write("E\n".getBytes()); os.flush(); } /** * Receive a file via scp and store it in a stream * * @param channel * ssh channel to use * @param file * to receive from remote * @param target * to store file into (if null, get only file info) * @return file information of the file we received * @throws IOException * in case of network or protocol trouble * @throws Exception * in case of problems on the target system (connection is fine) */ private FileInfo receiveStream(Channel channel, String file, OutputStream targetStream) throws IOException, Exception { byte[] buffer = new byte[BUFFER_SIZE]; OutputStream os = channel.getOutputStream(); InputStream is = channel.getInputStream(); try { if (channel.isConnected()) { channel.start(); } else { channel.connect(); } } catch (JSchException e1) { throw (IOException) new IOException("Channel connection problems") .initCause(e1); } os.write(0x0); os.flush(); FileInfo fileInfo = new FileInfo(); while (true) { int c = is.read(); if (c < 0) { throw new Exception("Remote scp terminated unexpectedly."); } String line = receiveLine(is); if (c == 'T') { parseTLine(line, fileInfo); os.write(0x0); os.flush(); continue; } if ((c == 1) || (c == 2)) { throw new Exception("Remote SCP error: " + line); } if (c == 'C') { parseCLine(line, fileInfo); break; } throw new Exception("Remote SCP error: " + ((char) c) + line); } if (targetStream != null) { os.write(0x0); os.flush(); try { long remain = fileInfo.getLength(); while (remain > 0) { int trans; if (remain > buffer.length) { trans = buffer.length; } else { trans = (int) remain; } int thisTimeReceived = is.read(buffer, 0, trans); if (thisTimeReceived < 0) { throw new IOException( "Remote scp terminated connection unexpectedly"); } targetStream.write(buffer, 0, thisTimeReceived); remain -= thisTimeReceived; } targetStream.close(); } catch (IOException e) { if (targetStream != null) { targetStream.close(); } LOGGER.error(e); throw (e); } readResponse(is); os.write(0x0); os.flush(); } return fileInfo; } /** * @return * @throws JSchException */ private ChannelExec getExecChannel() throws JSchException { ChannelExec channel; channel = (ChannelExec) session.openChannel("exec"); return channel; } /** * Copy a local file to a remote site, uses the specified mode when creating the file on the * remote side. * * @param localFile * Path and name of local file. Must be absolute. * @param remoteTargetDir * Remote target directory where the file has to end up (optional) * @param remoteTargetName * file name to use on the target system * @param mode * a four digit string (e.g., 0644, see "man chmod", "man open") * @throws IOException * in case of network problems * @throws Exception * in case of problems on the target system (connection ok) */ public void put(String localFile, String remoteTargetDir, String remoteTargetName, String mode) throws Exception { ChannelExec channel = null; if ((localFile == null) || (remoteTargetName == null)) { throw new IllegalArgumentException("Null argument."); } if (mode != null) { if (mode.length() != MODE_LENGTH) { throw new IllegalArgumentException("Invalid mode."); } for (int i = 0; i < mode.length(); i++) { if (!Character.isDigit(mode.charAt(i))) { throw new IllegalArgumentException("Invalid mode."); } } } String cmd = "scp -t "; if (mode != null) { cmd = cmd + "-p "; } if (remoteTargetDir != null && remoteTargetDir.length() > 0) { cmd = cmd + "-d " + remoteTargetDir; } try { channel = getExecChannel(); channel.setCommand(cmd); sendFile(channel, localFile, remoteTargetName, mode); channel.disconnect(); } catch (JSchException e) { if (channel != null) { channel.disconnect(); } e.printStackTrace(); LOGGER.error(e); throw new Exception("Error during SCP transfer." + e.getMessage()); } catch (Exception e) { e.printStackTrace(); LOGGER.error(e); throw new Exception(e.getLocalizedMessage()); } } /** * Download a file from the remote server to a local file. * * @param remoteFile * Path and name of the remote file. * @param localTarget * Local file where to store the data. Must be absolute. * @throws IOException * in case of network problems * @throws Exception * in case of problems on the target system (connection ok) */ public void get(String remoteFile, String localTarget) throws Exception { try { File f = new File(localTarget); FileOutputStream fop = new FileOutputStream(f); get(remoteFile, fop); } catch (IOException e) { e.printStackTrace(); LOGGER.error(e); throw new Exception(e.getLocalizedMessage()); } } /** * Download a file from the remote server into an OutputStream * * @param remoteFile * Path and name of the remote file. * @param localTarget * OutputStream to store the data. * @throws IOException * in case of network problems * @throws Exception * in case of problems on the target system (connection ok) */ private void get(String remoteFile, OutputStream localTarget) throws IOException, Exception { ChannelExec channel = null; if ((remoteFile == null) || (localTarget == null)) { throw new IllegalArgumentException("Null argument."); } String cmd = "scp -p -f " + remoteFile; try { channel = getExecChannel(); channel.setCommand(cmd); receiveStream(channel, remoteFile, localTarget); channel.disconnect(); } catch (JSchException e) { if (channel != null) { channel.disconnect(); } throw (IOException) new IOException("Error during SCP transfer." + e.getMessage()).initCause(e); } } /** * Initiates an SCP sequence but stops after getting fileinformation header * * @param remoteFile * to get information for * @return the file information got * @throws IOException * in case of network problems * @throws Exception * in case of problems on the target system (connection ok) */ public FileInfo getFileinfo(String remoteFile) throws IOException, Exception { ChannelExec channel = null; FileInfo fileInfo = null; if (remoteFile == null) { throw new IllegalArgumentException("Null argument."); } String cmd = "scp -p -f \"" + remoteFile + "\""; try { channel = getExecChannel(); channel.setCommand(cmd); fileInfo = receiveStream(channel, remoteFile, null); channel.disconnect(); } catch (JSchException e) { throw (IOException) new IOException("Error during SCP transfer." + e.getMessage()).initCause(e); } finally { if (channel != null) { channel.disconnect(); } } return fileInfo; } }


Fichier(s) joint(s) :