hydrograph.ui.communication.utilities.SCPUtility.java Source code

Java tutorial

Introduction

Here is the source code for hydrograph.ui.communication.utilities.SCPUtility.java

Source

/*******************************************************************************
 * Copyright 2017 Capital One Services, LLC and Bitwise, Inc.
 * Licensed 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 hydrograph.ui.communication.utilities;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;

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

import hydrograph.ui.communication.messages.Message;
import hydrograph.ui.communication.messages.MessageType;
import hydrograph.ui.logging.factory.LogFactory;

/**
 * The class SCPUtility
 * Provides utility methods to copy files using scp
 * 
 * @author Bitwise
 * 
 */
public class SCPUtility {
    private static final String STRICT_HOST_KEY_CHECKING_DEFAULT_VALUE = "no";
    private static final String STRICT_HOST_KEY_CHECKING = "StrictHostKeyChecking";
    private static final String PREFERRED_AUTHENTICATIONS_DEFAULT_VALUES = "publickey,keyboard-interactive,password";
    private static final String PREFERRED_AUTHENTICATIONS = "PreferredAuthentications";
    private static final int SSH_PORT = 22;
    private static final String GENERAL_SUCCESS_MESSAGE = "SUCCESS";
    private static final String GENERAL_ERROR_MESSAGE = "ERROR";
    private static final String AUTHENTICATION_FAILED_MESSAGE = "Invalid username or password";
    private static final String AUTH_FAIL_EXCEPTION = "Auth fail";
    private static final String UNKNOWN_HOST_MESSAGE = "Unknown host";
    private static final String UNKNOWN_HOST_EXCEPTION = "UnknownHostException";
    private static final Logger logger = LogFactory.INSTANCE.getLogger(SCPUtility.class);
    public static SCPUtility INSTANCE = new SCPUtility();

    private SCPUtility() {

    }

    public Message validateCredentials(String host, String user, String password) {

        JSch jsch = new JSch();

        Session session;
        try {
            session = jsch.getSession(user, host, SSH_PORT);

            session.setPassword(password);

            java.util.Properties config = new java.util.Properties();
            config.put(STRICT_HOST_KEY_CHECKING, STRICT_HOST_KEY_CHECKING_DEFAULT_VALUE);
            session.setConfig(config);

            session.setConfig(PREFERRED_AUTHENTICATIONS, PREFERRED_AUTHENTICATIONS_DEFAULT_VALUES);

            session.connect();
            session.disconnect();
        } catch (Exception e) {
            return getErrorMessage(e);
        }

        return new Message(MessageType.SUCCESS, GENERAL_SUCCESS_MESSAGE);
    }

    private Message getErrorMessage(Exception e) {
        if (StringUtils.contains(e.getMessage(), UNKNOWN_HOST_EXCEPTION)) {
            return new Message(MessageType.UNKNOWN_HOST, UNKNOWN_HOST_MESSAGE);
        } else if (StringUtils.contains(e.getMessage(), AUTH_FAIL_EXCEPTION)) {
            return new Message(MessageType.INVALID_USERNAME_PASSWORD, AUTHENTICATION_FAILED_MESSAGE);
        } else {
            return new Message(MessageType.ERROR, GENERAL_ERROR_MESSAGE);
        }
    }

    /**
     * 
     * Scp file from remote server
     * 
     * @param host
     * @param user
     * @param password
     * @param remoteFile
     * @param localFile
     * @throws JSchException 
     * @throws IOException 
     */
    public void scpFileFromRemoteServer(String host, String user, String password, String remoteFile,
            String localFile) throws JSchException, IOException {

        String prefix = null;
        if (new File(localFile).isDirectory()) {
            prefix = localFile + File.separator;
        }

        JSch jsch = new JSch();
        Session session = jsch.getSession(user, host, 22);

        // username and password will be given via UserInfo interface.
        UserInfo userInfo = new UserInformation(password);
        session.setUserInfo(userInfo);
        session.connect();

        // exec 'scp -f remoteFile' remotely
        String command = "scp -f " + remoteFile;
        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();

        readRemoteFileAndWriteToLocalFile(localFile, prefix, out, in, buf);

        session.disconnect();
    }

    private void readRemoteFileAndWriteToLocalFile(String localFile, String prefix, OutputStream out,
            InputStream in, byte[] buf) throws IOException, FileNotFoundException {
        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;
                }
            }

            // send '\0'
            buf[0] = 0;
            out.write(buf, 0, 1);
            out.flush();

            // read a content of local file
            try (FileOutputStream fos = new FileOutputStream(prefix == null ? localFile : 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;
                }
            } catch (IOException e) {
                throw e;
            }

            if (checkAck(in) != 0) {
                //System.exit(0);
                return;
            }

            // send '\0'
            buf[0] = 0;
            out.write(buf, 0, 1);
            out.flush();
        }
    }

    private 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
                logger.debug(sb.toString());
            }
            if (b == 2) { // fatal error
                logger.debug(sb.toString());
            }
        }
        return b;
    }

    /**
     * 
     * This class store user information who participates in scp
     * 
     * @author Bitwise
     * 
     */
    private static class UserInformation implements UserInfo {

        String password;

        public UserInformation(String password) {
            this.password = password;
        }

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

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

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

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

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

        @Override
        public void showMessage(String arg0) {

        }

    }

}