package alien4cloud.it.provider.util;

import java.io.FileReader;
import java.io.IOException;
import java.security.KeyPair;
import java.security.Security;

import lombok.extern.slf4j.Slf4j;

import org.apache.sshd.ClientSession;
import org.apache.sshd.SshClient;
import org.apache.sshd.client.ScpClient;
import org.apache.sshd.client.future.AuthFuture;
import org.apache.sshd.common.future.SshFutureListener;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;

@Slf4j
public class SSHUtil {

    private static KeyPair loadKeyPair(String pemFile) {
        try {
            Security.addProvider(new BouncyCastleProvider());
            PEMParser pemParser = new PEMParser(new FileReader(pemFile));
            JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
            Object object = pemParser.readObject();
            return converter.getKeyPair((PEMKeyPair) object);
        } catch (Exception e) {
            log.error("Could not load key pair", e);
            throw new RuntimeException("Could not load key pair", e);
        }
    }

    private static ClientSession connect(SshClient client, final String user, KeyPair keyPair, final String ip, final int port) throws IOException,
            InterruptedException {
        ClientSession session = client.connect(user, ip, port).await().getSession();
        int authState = ClientSession.WAIT_AUTH;
        while ((authState & ClientSession.WAIT_AUTH) != 0) {
            session.addPublicKeyIdentity(keyPair);
            log.info("Authenticating to " + user + "@" + ip);
            AuthFuture authFuture = session.auth();
            authFuture.addListener(new SshFutureListener<AuthFuture>() {
                @Override
                public void operationComplete(AuthFuture authFuture) {
                    log.info("Authentication completed with " + (authFuture.isSuccess() ? "success" : "failure") + " for " + user + "@" + ip + ":" + port);
                }
            });
            authState = session.waitFor(ClientSession.WAIT_AUTH | ClientSession.CLOSED | ClientSession.AUTHED, 0);
        }

        if ((authState & ClientSession.CLOSED) != 0) {
            throw new IOException("Authentication failed for " + user + "@" + ip);
        }
        return session;
    }

    private interface DoWithScpAction {
        void doScpAction(ScpClient scpClient) throws IOException;
    }

    private static void doWithScp(String user, String ip, int port, String pemPath, DoWithScpAction doWithScpAction) throws IOException, InterruptedException {
        SshClient client = SshClient.setUpDefaultClient();
        ClientSession session = null;
        try {
            client.start();
            session = connect(client, user, loadKeyPair(pemPath), ip, port);
            ScpClient scpClient = session.createScpClient();
            doWithScpAction.doScpAction(scpClient);
        } finally {
            if (session != null) {
                session.close(true);
            }
            client.close(true);
        }
    }

    public static void download(String user, String ip, int port, String pemPath, final String remote, final String local) throws IOException,
            InterruptedException {
        doWithScp(user, ip, port, pemPath, new DoWithScpAction() {
            @Override
            public void doScpAction(ScpClient scpClient) throws IOException {
                scpClient.download(remote, local, ScpClient.Option.Recursive);
            }
        });
    }

    public static void upload(String user, String ip, int port, String pemPath, final String remote, final String local) throws IOException,
            InterruptedException {
        doWithScp(user, ip, port, pemPath, new DoWithScpAction() {
            @Override
            public void doScpAction(ScpClient scpClient) throws IOException {
                scpClient.upload(local, remote, ScpClient.Option.Recursive);
            }
        });
    }
}

@@ -3110,27 +3110,28 @@
 ssion.close(
-tru
+fals
 e);%0A        
@@ -3165,11 +3165,12 @@
 ose(
-tru
+fals
 e);%0A

Fix tests