content: 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);
              }
          });
      }
  }
  