Package com.slim.utils

Source Code of com.slim.utils.SSHClientUtils$MyUserInfo

package com.slim.utils;

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.maven.plugin.logging.Log;

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 SSHClientUtils {

  private static final String END_KSH = "end.ksh";

  /** 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 final 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 final Pattern alphaNumeric = Pattern.compile("([^a-zA-z0-9])");

  private int nbChannel = 0;

  private String previousMode;

  private final int SERVER_RESPONSE_TIMEOUT = 1500;

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

  /** Shell */
  private final JSch shell;

  private final Log LOGGER;

  public SSHClientUtils(String host, String user, String password, Log logger) throws Exception {
    LOGGER = logger;
    shell = new JSch();
    USER = user;
    PWD = password;
    HOST = host;
    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();
      scp = new Scp(session);
    } catch (JSchException e) {
      e.printStackTrace();
      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();
        }
        // Pour laisser le temps de se connecter
        Thread.sleep(100);
      } catch (Exception e) {
        e.printStackTrace();
        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, String workingDir) throws Exception {

    String endScript = workingDir + "/" + END_KSH;

    sendShell("echo \"echo " + TERMINATOR + "\" > " + endScript);
    sendShell("chmod 0777 " + endScript);

    connect(SHELL_MODE);
    lastCommand = command;

    command += "; " + endScript + " \n";
    command = endScript + "; " + command;
    try {
      toServer.write(command.getBytes());
      // To ensure server answer reception
      // and manage a communication time out.

      Thread.sleep(SERVER_RESPONSE_TIMEOUT);

    } catch (IOException ex) {
      ex.printStackTrace();
      throw new Exception(ex.getLocalizedMessage());
    } catch (InterruptedException iex) {
      iex.printStackTrace();
      throw new Exception(iex.getLocalizedMessage());
    }

    String rep = getServerResponse();
    sendShell("rm " + endScript);
    return rep;
  }

  /**
   *
   * @param command
   * @return
   * @throws Exception
   */
  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.

      Thread.sleep(SERVER_RESPONSE_TIMEOUT);

    } catch (IOException ex) {
      ex.printStackTrace();
      throw new Exception(ex.getLocalizedMessage());
    } catch (InterruptedException iex) {
      iex.printStackTrace();
      throw new Exception(iex.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 > 0) {
            LOGGER.info(line);
          }

          if (line.indexOf(TERMINATOR) != -1 && ++count > 1) {
            break;
          }
        }
        result = builder.toString();

        result = result.substring(result.indexOf(TERMINATOR), result.lastIndexOf(TERMINATOR));
        result = result.replaceAll(escape(TERMINATOR), "").trim();
        LOGGER.debug("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 <CODE>exec 'scp -t rfile'</CODE>
   * 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<String> getResultsFiles(String remotePath, String localDestinationPath) throws Exception {
    List<String> filesPaths = new ArrayList<String>();
    // 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<String> 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<String> getFilesList(String lsResult) {
    List<String> files = new ArrayList<String>();
    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;
    }

    @Override
    public String getPassphrase() {
      return null;
    }

    @Override
    public String getPassword() {
      return password;
    }

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

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

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

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

Related Classes of com.slim.utils.SSHClientUtils$MyUserInfo

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.