cycronix.ctlib.CTftp.java Source code

Java tutorial

Introduction

Here is the source code for cycronix.ctlib.CTftp.java

Source

/*
Copyright 2018 Cycronix
     
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 cycronix.ctlib;

import java.io.File;

//---------------------------------------------------------------------------------   
// CTftp:  push files to FTP server
// Matt Miller, Cycronix
// 06/22/2015

import java.io.IOException;
import java.io.OutputStream;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPSClient;

/**
 * CloudTurbine utility class that extends CTwriter class to write via FTP versus local filesystem
 * <p>
 * @author Matt Miller (MJM), Cycronix
 * @version 2015/06/01
 * 
*/

public class CTftp extends CTwriter {

    private FTPClient client = null;
    private String loginDir = "";
    private String currentDir = "";

    //------------------------------------------------------------------------------------------------
    // constructor
    /**
     * Constructor
     * @param dstFolder destination folder on remote host
     * @throws IOException on error
     */
    public CTftp(String dstFolder) throws IOException {
        super(dstFolder);
    }

    /**
     * Constructor
     * @param dstFolder destination folder on remote host
     * @param itrimTime trim-time for data writes
     * @throws IOException on error
     */
    public CTftp(String dstFolder, double itrimTime) throws IOException {
        super(dstFolder);
        throw new IOException("CTftp does not yet support file trim");
    }

    //------------------------------------------------------------------------------------------------
    /**
     * FTP login by providing username and password
     * @param host host name
     * @param user user name
     * @param pw password
     * @throws Exception on error
     */
    public void login(String host, String user, String pw) throws Exception {
        login(host, user, pw, false);
    }

    /**
     * FTP login with secure (FTPS) connection
     * @param host host name
     * @param user user name
     * @param pw password
     * @param secure T/F
     * @throws Exception on error
     */
    public void login(String host, String user, String pw, boolean secure) throws Exception {
        if (secure)
            client = new FTPSClient(true);
        else
            client = new FTPClient();

        client.connect(host);
        boolean success = client.login(user, pw);
        if (!success) {
            throw new IOException("FTP login failed, host: " + host + ", user: " + user);
        }
        client.setFileType(FTPClient.BINARY_FILE_TYPE);

        loginDir = client.printWorkingDirectory();
        CTinfo.debugPrint("FTP login, u: " + user + ", pw: " + pw + ", loginDir: " + loginDir);
    }

    /**
     * logout of FTP connection
     */
    public void logout() {
        try {
            client.logout();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // over-ride CTwriter method to replace file-writes with FTP write
    protected void writeToStream(String pathname, byte[] bdata) throws IOException {
        try {
            if (!File.separator.equals("/")) { // replace Windows back-slash with slash for hopefully universal FTP syntax
                pathname = pathname.replace(File.separator.charAt(0), '/');
            }
            int delim = pathname.lastIndexOf('/');
            String filename = pathname.substring(delim + 1);
            String filepath = pathname.substring(0, delim);

            if (!filepath.equals(currentDir)) { // create or change to new directory if changed from previous
                if (pathname.startsWith("/"))
                    client.changeWorkingDirectory("/");
                else
                    client.changeWorkingDirectory(loginDir); // new dirs relative to loginDir
                ftpCreateDirectoryTree(client, filepath); // mkdirs as needed, leaves working dir @ new
                currentDir = filepath;
            }

            CTinfo.debugPrint("ftp pathname: " + pathname + ", filename: " + filename + ", filepath: " + filepath);

            OutputStream ostream = client.storeFileStream(filename + ".tmp");
            //         OutputStream ostream = client.storeFileStream(filename);            // try without tmp file
            if (ostream == null) {
                System.err.println("CTftp, bad FTP connection, try again: " + client.getReplyString());
                ostream = client.storeFileStream(filename + ".tmp"); // try again?
                if (ostream == null) {
                    String ereply = client.getReplyString();
                    System.err.println("CTftp, bad FTP connection, throw exception: " + ereply);
                    client.deleteFile(filename + ".tmp"); // try not to orphan empty tmp file
                    throw new IOException("Bad FTP connection, file: " + filename + ", status: " + ereply);
                }
            }

            ostream.write(bdata);
            ostream.close();
            if (!client.completePendingCommand()) {
                String ereply = client.getReplyString();
                client.deleteFile(filename + ".tmp"); // try not to orphan empty tmp file
                throw new IOException("Unable to FTP file: " + ereply);
            }

            if (!client.rename(filename + ".tmp", filename)) // rename to actual filename
                throw new IOException(
                        "Unable to rename file: " + filename + ", status: " + client.getReplyString());

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
    * utility to create an arbitrary directory hierarchy on the remote ftp server 
    * @param client
    * @param dirTree  the directory tree only delimited with / chars.  No file name!
    * @throws Exception
    */
    private static void ftpCreateDirectoryTree(FTPClient client, String dirTree) throws IOException {
        boolean dirExists = true;
        //tokenize the string and attempt to change into each directory level.  If you cannot, then start creating.
        String[] directories = dirTree.split("/");
        for (String dir : directories) {

            if (!dir.isEmpty()) {
                if (dirExists) {
                    dirExists = client.changeWorkingDirectory(dir);
                }

                if (!dirExists) {
                    try {
                        if (!client.makeDirectory(dir)) {
                            throw new IOException("Unable to create remote directory: " + dir + ", error="
                                    + client.getReplyString());
                        }
                        if (!client.changeWorkingDirectory(dir)) {
                            throw new IOException("Unable to change into newly created remote directory: " + dir
                                    + ", error=" + client.getReplyString());
                        }
                    } catch (IOException ioe) {
                        //                  System.err.println("ftpCreateDir exception on dirTree: "+dirTree+", dir: "+dir+", error: "+ioe.getMessage());
                        throw ioe;
                    }
                }
            }
        }
    }
}