content: /**
   * 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.alibaba.jstorm.yarn.utils;
  /* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
  /**
   * This program will demonstrate the file transfer from remote to local
   * $ CLASSPATH=.:../build javac ScpFrom.java
   * $ CLASSPATH=.:../build java ScpFrom user@remotehost:file1 file2
   * You will be asked passwd.
   * If everything works fine, a file 'file1' on 'remotehost' will copied to
   * local 'file1'.
   */
  
  import com.jcraft.jsch.*;
  
  import javax.swing.*;
  import java.awt.*;
  import java.io.*;
  
  public class ScpFrom {
  
      public ScpFrom(String host, String username, String password) {
          this.host = host;
          this.username = username;
          this.password = password;
      }
  
      private String host;
      private String username;
      private String password;
  
      public void getRemoteFile(String remoteFile, String localDir) throws Exception {
          String[] arg = new String[]{username + "@" + host + ":" + remoteFile, localDir};
  
          FileOutputStream fos = null;
          try {
  
              String user = arg[0].substring(0, arg[0].indexOf('@'));
              arg[0] = arg[0].substring(arg[0].indexOf('@') + 1);
              String host = arg[0].substring(0, arg[0].indexOf(':'));
              String rfile = arg[0].substring(arg[0].indexOf(':') + 1);
              String lfile = arg[1];
  
              String prefix = null;
              if (new File(lfile).isDirectory()) {
                  prefix = lfile + File.separator;
              }
  
              JSch jsch = new JSch();
              Session session = jsch.getSession(user, host, 22);
  
              session.setPassword(password);
              session.setConfig("StrictHostKeyChecking", "no");
              session.connect();
  
              String command = "scp -f " + rfile;
              Channel channel = session.openChannel("exec");
              ((ChannelExec) channel).setCommand(command);
  
              // get I/O streams for remote scp
              OutputStream out = channel.getOutputStream();
              InputStream in = channel.getInputStream();
  
              channel.connect();
  
              byte[] buf = new byte[1024];
  
              // send '\0'
              buf[0] = 0;
              out.write(buf, 0, 1);
              out.flush();
  
              while (true) {
                  int c = checkAck(in);
                  if (c != 'C') {
                      break;
                  }
  
                  // read '0644 '
                  in.read(buf, 0, 5);
  
                  long filesize = 0L;
                  while (true) {
                      if (in.read(buf, 0, 1) < 0) {
                          // error
                          break;
                      }
                      if (buf[0] == ' ') break;
                      filesize = filesize * 10L + (long) (buf[0] - '0');
                  }
  
                  String file = null;
                  for (int i = 0; ; i++) {
                      in.read(buf, i, 1);
                      if (buf[i] == (byte) 0x0a) {
                          file = new String(buf, 0, i);
                          break;
                      }
                  }
  
                  buf[0] = 0;
                  out.write(buf, 0, 1);
                  out.flush();
  
                  // read a content of lfile
                  fos = new FileOutputStream(prefix == null ? lfile : prefix + file);
                  int foo;
                  while (true) {
                      if (buf.length < filesize) foo = buf.length;
                      else foo = (int) filesize;
                      foo = in.read(buf, 0, foo);
                      if (foo < 0) {
                          // error
                          break;
                      }
                      fos.write(buf, 0, foo);
                      filesize -= foo;
                      if (filesize == 0L) break;
                  }
                  fos.close();
                  fos = null;
  
                  if (checkAck(in) != 0) {
                      throw new Exception("error checkAck is not 0");
                  }
  
                  // send '\0'
                  buf[0] = 0;
                  out.write(buf, 0, 1);
                  out.flush();
              }
  
              session.disconnect();
  
          } catch (Exception e) {
              try {
                  if (fos != null) fos.close();
              } catch (Exception ee) {
              }
              throw e;
          }
      }
  
      public static void main(String[] arg) {
  //        if (arg.length != 2) {
  //            System.err.println("usage: java ScpFrom user@remotehost:file1 file2");
  //            System.exit(-1);
  //        }
          arg = new String[]{"fengjian@localhost:~/code/storm-benchmark.tar", "/Users/fengjian"};
  
          FileOutputStream fos = null;
          try {
  
              String user = arg[0].substring(0, arg[0].indexOf('@'));
              arg[0] = arg[0].substring(arg[0].indexOf('@') + 1);
              String host = arg[0].substring(0, arg[0].indexOf(':'));
              String rfile = arg[0].substring(arg[0].indexOf(':') + 1);
              String lfile = arg[1];
  
              String prefix = null;
              if (new File(lfile).isDirectory()) {
                  prefix = lfile + File.separator;
              }
  
              JSch jsch = new JSch();
              Session session = jsch.getSession(user, host, 22);
  
              // username and password will be given via UserInfo interface.
  //            UserInfo ui = new MyUserInfo();
  //            UserInfo ui = new MyUserInfo1();
  //            session.setUserInfo(ui);
              session.setPassword("123fj");
              session.setConfig("StrictHostKeyChecking", "no");
              session.connect();
  
              // exec 'scp -f rfile' remotely
  //            String command = "cd ~/ && tar -xf storm-benchmark.tar && scp -f " + rfile;
              String command = "scp -f " + rfile;
              Channel channel = session.openChannel("exec");
              ((ChannelExec) channel).setCommand(command);
  
              // get I/O streams for remote scp
              OutputStream out = channel.getOutputStream();
              InputStream in = channel.getInputStream();
  
              channel.connect();
  
              byte[] buf = new byte[1024];
  
              // send '\0'
              buf[0] = 0;
              out.write(buf, 0, 1);
              out.flush();
  
              while (true) {
                  int c = checkAck(in);
                  if (c != 'C') {
                      break;
                  }
  
                  // read '0644 '
                  in.read(buf, 0, 5);
  
                  long filesize = 0L;
                  while (true) {
                      if (in.read(buf, 0, 1) < 0) {
                          // error
                          break;
                      }
                      if (buf[0] == ' ') break;
                      filesize = filesize * 10L + (long) (buf[0] - '0');
                  }
  
                  String file = null;
                  for (int i = 0; ; i++) {
                      in.read(buf, i, 1);
                      if (buf[i] == (byte) 0x0a) {
                          file = new String(buf, 0, i);
                          break;
                      }
                  }
  
                  //System.out.println("filesize="+filesize+", file="+file);
  
                  // send '\0'
                  buf[0] = 0;
                  out.write(buf, 0, 1);
                  out.flush();
  
                  // read a content of lfile
                  fos = new FileOutputStream(prefix == null ? lfile : prefix + file);
                  int foo;
                  while (true) {
                      if (buf.length < filesize) foo = buf.length;
                      else foo = (int) filesize;
                      foo = in.read(buf, 0, foo);
                      if (foo < 0) {
                          // error
                          break;
                      }
                      fos.write(buf, 0, foo);
                      filesize -= foo;
                      if (filesize == 0L) break;
                  }
                  fos.close();
                  fos = null;
  
                  if (checkAck(in) != 0) {
                      System.exit(0);
                  }
  
                  // send '\0'
                  buf[0] = 0;
                  out.write(buf, 0, 1);
                  out.flush();
              }
  
              session.disconnect();
  
              System.exit(0);
          } catch (Exception e) {
              System.out.println(e);
              try {
                  if (fos != null) fos.close();
              } catch (Exception ee) {
              }
          }
      }
  
      static int checkAck(InputStream in) throws IOException {
          int b = in.read();
          // b may be 0 for success,
          //          1 for error,
          //          2 for fatal error,
          //          -1
          if (b == 0) return b;
          if (b == -1) return b;
  
          if (b == 1 || b == 2) {
              StringBuffer sb = new StringBuffer();
              int c;
              do {
                  c = in.read();
                  sb.append((char) c);
              }
              while (c != '\n');
              if (b == 1) { // error
  //                System.out.print(sb.toString());
              }
              if (b == 2) { // fatal error
  //                System.out.print(sb.toString());
              }
          }
          return b;
      }
  }