Tuesday, October 12, 2010

Copy files from/to between local and HTTP(s), (S)FTP, local, mail filesystems

Using Apache VFS. Sweet.

package jobs;

import org.apache.commons.vfs.FileFilter;
import org.apache.commons.vfs.FileFilterSelector;
import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSelectInfo;
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileSystemOptions;
import org.apache.commons.vfs.impl.StandardFileSystemManager;
import org.apache.commons.vfs.provider.sftp.SftpFileSystemConfigBuilder;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FileCopyJob implements Job {
    Logger log = LoggerFactory.getLogger(getClass());
    String fileNameStartsWith = null;
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        long startPoint = System.nanoTime();
        log.info("Reading config.");
        JobDataMap data = context.getJobDetail().getJobDataMap();
        String fromDirURL = data.getString("fromDirURL");
        String toDirURL = data.getString("toDirURL");
        fileNameStartsWith = data.getString("fileNameStartsWith");
        log.debug("fromDirURL=                 {}",fromDirURL);
        log.debug("toDirURL=                   {}",toDirURL);
        log.debug("fileNameStartsWith=       {}",fileNameStartsWith);
        log.info("Instantiating File System Manager (FSM).");
        StandardFileSystemManager fileSystemManager = null;
        FileObject fromDirFileObject = null;
        FileObject toDirFileObject   = null;
        try {
            fileSystemManager = new StandardFileSystemManager();
            log.info("Creating file objects.");
            FileSystemOptions opts = new FileSystemOptions();
            SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(opts, "no");
            fileSystemManager.init();
            fromDirFileObject = fileSystemManager.resolveFile(fromDirURL,opts);
            toDirFileObject = fileSystemManager.resolveFile(toDirURL,opts);
            Boolean fromDirFileObjectExists = fromDirFileObject.exists();
            Boolean toDirFileObjectExists = toDirFileObject.exists();
            log.info("fromDirFileObjectExists? {}", fromDirFileObjectExists);
            log.info("toDirFileObjectExists?   {}", toDirFileObjectExists);
            if (fromDirFileObjectExists==false || toDirFileObjectExists==false) {
                log.error("Please check file paths, either directory does not exist.");
                throw new RuntimeException("Directory does not exists.");
            }
            FileFilter ff = new FileFilter()
            {
                public boolean accept(FileSelectInfo fileInfo)
                {
                    FileObject fo = fileInfo.getFile();
                    return fo.getName().getBaseName().startsWith(fileNameStartsWith);
                }
            };
            FileObject[] foundFiles = null;
            foundFiles = fromDirFileObject.findFiles(new FileFilterSelector(ff));
            if (foundFiles.length < 1 ) {
            log.info("No files found.");   
            } else {
                for (FileObject foundFile:foundFiles) {
                    String baseName = foundFile.getName().getBaseName();
                    String destinationFullName = toDirURL + toDirFileObject.getName().SEPARATOR + baseName;
                    log.debug("Trying to move {} into {}",baseName,destinationFullName);
                    foundFile.moveTo(fileSystemManager.resolveFile(destinationFullName,opts));
                    log.info("Moved {}",foundFile);
                }
            } // no code beyond this point
        } catch (FileSystemException e) {
            log.error("Something bad happened with the file system you are trying to reach. ", e);
        } finally {
            log.info("Closing FSM.");
            fileSystemManager.close();
        }
        long endPoint = System.nanoTime();
        log.info("Operation took {} nanoseconds.", (endPoint-startPoint));
    }
}