com.qpark.eip.core.sftp.SftpDownload.java Source code

Java tutorial

Introduction

Here is the source code for com.qpark.eip.core.sftp.SftpDownload.java

Source

/*******************************************************************************
 * Copyright (c) 2013, 2014, 2015 QPark Consulting  S.a r.l.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0.
 * The Eclipse Public License is available at
 * http://www.eclipse.org/legal/epl-v10.html.
 ******************************************************************************/
package com.qpark.eip.core.sftp;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.Random;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * @author bhausen
 */
public class SftpDownload {
    /**
     * Random object used by random method. This has to be not local to the
     * random method so as to not return the same value in the same millisecond.
     */
    private static final Random RANDOM = new Random();

    private static int nextRandomInt(final int startInclusive, final int endExclusive) {
        return startInclusive + RANDOM.nextInt(endExclusive - startInclusive);
    }

    /** The {@link org.slf4j.Logger}. */
    private final Logger logger = LoggerFactory.getLogger(SftpDownload.class);

    /** The {@link SftpGateway}. */
    @Autowired
    private SftpGateway sftpGateway;

    /**
     * Get the {@link Optional} of the file content. This could be empty,
     * because possibly another thread already read the content of the file path
     * and removed it.
     *
     * @param filePath
     *            the file path.
     * @return the {@link Optional} of the file content.
     */
    private Optional<byte[]> getFilePathContent(final String filePath) {
        Optional<byte[]> value = Optional.empty();
        try {
            final byte[] fileContent = this.sftpGateway.retrieveAndRead(filePath);
            value = Optional.of(fileContent);
        } catch (final Exception e) {
            // The file was eventually read by another thread.
        }
        return value;
    }

    /**
     * Get the file content, parse it and move the file to failed or done
     * directory.
     *
     * @param typeFactory
     *            the factory creating a list of T.
     * @param baseDir
     *            base source directory to get the files from (e.g. incoming)
     * @param filePath
     *            the file path.
     * @return the Optional of the parsed object of type.
     */
    public <T> List<T> getObject(final TypeFactory<T> typeFactory, final String baseDir, final String filePath) {
        this.logger.debug("+getObject {}", filePath);
        List<T> value = new ArrayList<>();
        String filePathDestination;
        final String filePathLoading = String.format("%s.%03d.loading", filePath, nextRandomInt(0, 999));
        try {
            filePathDestination = filePath.replace(SftpGateway.DIRECTORY_OPEN, SftpGateway.DIRECTORY_DONE);

            this.sftpGateway.rename(filePath, filePathLoading);
            final Optional<byte[]> filePathContent = this.getFilePathContent(filePathLoading);

            try {
                value = typeFactory.create(filePathContent);
            } catch (final Exception e) {
                this.logger.error(e.getMessage(), e);
                filePathDestination = filePath.replace(SftpGateway.DIRECTORY_OPEN, SftpGateway.DIRECTORY_FAILED);
            }
            try {
                this.sftpGateway.rename(filePathLoading, filePathDestination);
            } catch (final Exception e) {
                this.logger.error(String.format("%s:%s", filePathDestination, e.getMessage()), e);
            }
        } catch (final Exception e) {
            filePathDestination = filePath.replace(SftpGateway.DIRECTORY_OPEN, SftpGateway.DIRECTORY_FAILED);
            try {
                this.sftpGateway.rename(filePathLoading, filePathDestination);
            } catch (final Exception ex) {
                this.logger.error(String.format("%s:%s", filePathDestination, e.getMessage()), e);
            }
            this.logger.error(String.format("%s:%s", filePath, e.getMessage()), e);
        } finally {
            this.logger.debug("-getObject {}", filePath);
        }
        return value;
    }

    /**
     * Get the list of Objects from the SFTP.
     *
     * @param typeFactory
     *            the factory creating a list of T.
     * @param baseDir
     *            base source directory to get the files from (e.g. incoming)
     * @param fileNamePart
     *            the part, the file name need to contain (e.g. logs).
     * @param fileFormat
     *            the file format (e.g. xml, txt, json ...)
     * @return the list of Objects.
     */
    public <T> List<T> getObjects(final TypeFactory<T> typeFactory, final String baseDir, final String fileNamePart,
            final String fileFormat) {
        this.logger.debug("+getObjects");
        final List<T> value = new ArrayList<>();
        final String sourceDir = this.sftpGateway.getFilePath(baseDir, SftpGateway.DIRECTORY_OPEN);
        try {
            final Collection<String> filePathes = this.sftpGateway.getTreeOfFiles(sourceDir,
                    String.format("20.*?%s.%s", fileNamePart, fileFormat));
            filePathes.stream().sorted()
                    .forEach(filePath -> value.addAll(this.getObject(typeFactory, baseDir, filePath)));
        } catch (final Exception e) {
            this.logger.error(String.format("%s:%s", sourceDir, e.getMessage()), e);
        } finally {
            this.logger.debug("-getObjects {} #{}", sourceDir, value.size());
        }
        return value;
    }
}