All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.crabshue.commons.archive.s3.AwsS3ArchiveService Maven / Gradle / Ivy

The newest version!
package com.crabshue.commons.archive.s3;

import java.io.File;
import java.io.InputStream;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.filefilter.FileFilterUtils;

import com.amazonaws.services.s3.model.S3ObjectSummary;
import com.crabshue.commons.archive.Archivable;
import com.crabshue.commons.archive.ArchiveService;
import com.crabshue.commons.aws.s3.service.AwsS3Client;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;

/**
 * Abstract class for AWS-S3-based archive service.
 *
 * @param  the type of archivable.
 */
@Slf4j
public abstract class AwsS3ArchiveService implements ArchiveService {

    protected final AwsS3Client awsS3Client;

    protected AwsS3ArchiveService(final AwsS3Client awsS3Client) {
        this.awsS3Client = awsS3Client;
    }

    @Override
    public abstract String getArchiveRootPath();

    @Override
    public String getArchiveFolderPath(@NonNull final T archivable) {

        if (archivable.getArchiveId() == null) {
            throw new IllegalArgumentException("Archivable has a blank archive id: " + archivable);
        }

        final String ret = FilenameUtils.separatorsToUnix(
            Paths.get(this.getArchiveRootPath()).resolve(archivable.getArchiveId()).toString()
        ) + "/";

        logger.info("Archive folder path for archivable [{}] is [{}]", archivable, ret);
        return ret;
    }

    @Override
    public Collection listFilesInArchive(@NonNull final T archivable) {

        final String folderPath = this.getArchiveFolderPath(archivable);

        final List ret = this.awsS3Client.listObjects(folderPath)
            .stream()
            .map(S3ObjectSummary::getKey)
            .collect(Collectors.toList());

        logger.info("Listed files in [{}] for archivable [{}] : [{}]", folderPath, archivable, ret);
        return ret;

    }

    @Override
    public File retrieveUniqueFileInArchive(@NonNull final T archivable,
                                            @NonNull final String filename) {

        final String filePath = this.buildFilePath(archivable, filename);
        final File outputFile = new File(this.provideNewTemporaryFolder(), filename);
        this.awsS3Client.downloadObject(filePath, outputFile);

        logger.info("Retrieved file [{}] for archivable [{}] and filename [{}]", filePath, archivable, filename);
        return outputFile;
    }

    @Override
    public void deleteArchiveFolder(@NonNull final T archivable) {

        this.cleanArchiveFolder(archivable);

        final String folderPath = this.getArchiveFolderPath(archivable);
        this.awsS3Client.deleteObject(folderPath);

        logger.info("Deleted archive folder [{}] for archivable [{}]", folderPath, archivable);
    }

    @Override
    public void cleanArchiveFolder(@NonNull final T archivable) {

        final String folderPath = this.getArchiveFolderPath(archivable);

        final List keysToDelete = this.awsS3Client.listObjects(folderPath).stream()
            .map(S3ObjectSummary::getKey)
            .collect(Collectors.toList());

        this.awsS3Client.deleteObjects(keysToDelete);
        logger.info("Deleted content of folder [{}] for archivable [{}]", folderPath, archivable);
    }

    @Override
    public void cleanArchiveRoot() {
        this.awsS3Client.listObjects(this.getArchiveRootPath())
            .forEach(s3ObjectSummary -> this.awsS3Client.deleteObject(s3ObjectSummary.getKey()));

        logger.info("Cleaned all elements in archive root [{}]", this.getArchiveRootPath());
    }

    @Override
    public void storeInArchive(@NonNull final T archivable,
                               @NonNull final File file) {

        final String filePath = this.buildFilePath(archivable, file.getName());
        this.awsS3Client.uploadObject(filePath, file);

        logger.info("Stored file [{}] file in [{}] for archivable [{}]", file, filePath, archivable);
    }

    @Override
    public void storeInArchive(@NonNull final T archivable,
                               @NonNull final String filename,
                               @NonNull final InputStream inputStream) {

        final String filePath = this.buildFilePath(archivable, filename);
        this.awsS3Client.uploadObject(filePath, inputStream);

        logger.info("Stored input stream to [{}] for archivable [{}]", filePath, archivable);

    }

    @Override
    public void storeFolderContentInArchive(@NonNull final T archivable,
                                            @NonNull final File folder) {

        FileUtils.listFiles(folder, FileFilterUtils.trueFileFilter(), FileFilterUtils.trueFileFilter())
            .forEach(f -> {
                final String relativePath = folder.toPath().relativize(f.toPath()).toString();
                final String fileKey = this.buildFilePath(archivable, relativePath);
                this.awsS3Client.uploadObject(fileKey, f);
            });

        logger.info("Copied content of folder [{}] to archive folder for archivable [{}]", folder, archivable);
    }

    /**
     * Build key for a relative file path inside an archivable folder.
     *
     * @param archivable the archivable.
     * @param filePath   the file path.
     * @return the storage key
     */
    protected String buildFilePath(@NonNull final T archivable,
                                   @NonNull final String filePath) {
        final String ret = FilenameUtils.separatorsToUnix(Paths.get(this.getArchiveFolderPath(archivable)).resolve(filePath).toString());
        logger.debug("Built file path [{}] for file path [{}] and archivable [{}]", ret, filePath, archivable);
        return ret;
    }

    /**
     * Provide an empty temporary folder.
     * 

By default, use {@link FileUtils#getTempDirectory()}

* * @return the temporary folder. */ protected File provideNewTemporaryFolder() { return FileUtils.getTempDirectory(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy