io.milton.s3.AmazonS3ManagerImpl.java Source code

Java tutorial

Introduction

Here is the source code for io.milton.s3.AmazonS3ManagerImpl.java

Source

/*
 * Copyright (C) McEvoy Software Ltd
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package io.milton.s3;

import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

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

import com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.auth.ClasspathPropertiesFileCredentialsProvider;
import com.amazonaws.regions.Region;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.AccessControlList;
import com.amazonaws.services.s3.model.Bucket;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.CopyObjectRequest;
import com.amazonaws.services.s3.model.CopyObjectResult;
import com.amazonaws.services.s3.model.DeleteObjectsRequest;
import com.amazonaws.services.s3.model.DeleteObjectsRequest.KeyVersion;
import com.amazonaws.services.s3.model.DeleteObjectsResult;
import com.amazonaws.services.s3.model.GetObjectRequest;
import com.amazonaws.services.s3.model.Grant;
import com.amazonaws.services.s3.model.ListObjectsRequest;
import com.amazonaws.services.s3.model.ObjectListing;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.Permission;
import com.amazonaws.services.s3.model.PutObjectResult;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.s3.model.S3ObjectSummary;

public class AmazonS3ManagerImpl implements AmazonS3Manager {

    private static final Logger LOG = LoggerFactory.getLogger(AmazonS3ManagerImpl.class);

    // Amazon S3 Client
    private final AmazonS3 amazonS3Client;

    /**
     * You can choose the geographical region where Amazon S3 will store the
     * buckets you create. You might choose a region to optimize latency,
     * minimize costs, or address regulator requirements.
     * 
     * @param region
     */
    public AmazonS3ManagerImpl(Region region) {
        LOG.info("Create an instance of the AmazonS3Client class by providing your "
                + "AWS Account or IAM user credentials (Access Key ID, Secret Access Key)");

        // Create an instance of the AmazonS3Client class by providing your AWS
        // Account or IAM user credentials (Access Key ID, Secret Access Key)
        amazonS3Client = new AmazonS3Client(new ClasspathPropertiesFileCredentialsProvider());
        amazonS3Client.setRegion(region);
    }

    @Override
    public boolean isRootBucket(String bucketName) {
        LOG.info("Checks if the specified bucket " + bucketName + " exists or not");

        try {
            return amazonS3Client.doesBucketExist(bucketName);
        } catch (AmazonServiceException ase) {
            LOG.error(ase.getMessage(), ase);
        } catch (AmazonClientException ace) {
            LOG.error(ace.getMessage(), ace);
        }
        return false;
    }

    @Override
    public Bucket createBucket(String bucketName) {
        try {
            // Checks if the specified bucket exists or not and
            // if doesn't exist then creates a new Amazon S3 bucket
            // with the specified name in the default (US) region
            boolean isBucketExist = isRootBucket(bucketName);
            if (!isBucketExist) {
                LOG.info("Creates a new Amazon S3 bucket " + bucketName
                        + " with the specified name in the default (US) region");
                return amazonS3Client.createBucket(bucketName);
            }

            List<Bucket> buckets = findBuckets();
            if (!buckets.isEmpty()) {
                for (Bucket bucket : buckets) {
                    if (bucket.getName().equals(bucketName)) {
                        return bucket;
                    }
                }
            }
        } catch (AmazonServiceException ase) {
            LOG.error(ase.getMessage(), ase);
        } catch (AmazonClientException ace) {
            LOG.error(ace.getMessage(), ace);
        }
        return null;
    }

    @Override
    public boolean deleteBucket(String bucketName) {
        LOG.info("Deletes the specified bucket " + bucketName);

        try {
            // Make sure delete all the entities in the bucket
            deleteEntities(bucketName);
            // Delete the specified bucket for the given name
            amazonS3Client.deleteBucket(bucketName);
            return true;
        } catch (AmazonServiceException ase) {
            LOG.error(ase.getMessage(), ase);
        } catch (AmazonClientException ace) {
            LOG.error(ace.getMessage(), ace);
        }
        return false;
    }

    @Override
    public List<Bucket> findBuckets() {
        LOG.info("Returns a list of all Amazon S3 buckets that the authenticated " + "sender of the request owns");

        try {
            return amazonS3Client.listBuckets();
        } catch (AmazonServiceException ase) {
            LOG.error(ase.getMessage(), ase);
        } catch (AmazonClientException ace) {
            LOG.error(ace.getMessage(), ace);
        }
        return Collections.emptyList();
    }

    @Override
    public boolean uploadEntity(String bucketName, String keyName, File file) {
        LOG.info("Uploads the specified file " + file + " to Amazon S3 under the specified bucket " + bucketName
                + " and key name " + keyName);

        try {
            PutObjectResult putObjectResult = amazonS3Client.putObject(bucketName, keyName, file);
            if (putObjectResult != null) {
                return true;
            }
        } catch (AmazonServiceException ase) {
            LOG.error(ase.getMessage(), ase);
        } catch (AmazonClientException ace) {
            LOG.error(ace.getMessage(), ace);
        }
        return false;
    }

    @Override
    public boolean uploadEntity(String bucketName, String keyName, InputStream inputStream,
            ObjectMetadata metadata) {
        LOG.info("Uploads the specified input stream " + inputStream
                + " and object metadata to Amazon S3 under the specified bucket " + bucketName + " and key name "
                + keyName);

        try {
            PutObjectResult putObjectResult = amazonS3Client.putObject(bucketName, keyName, inputStream, metadata);
            if (putObjectResult != null) {
                LOG.info("Upload the specified input stream " + inputStream + " state: " + putObjectResult);
                return true;
            }
        } catch (AmazonServiceException ase) {
            LOG.warn(ase.getMessage(), ase);
        } catch (AmazonClientException ace) {
            LOG.warn(ace.getMessage(), ace);
        }
        return false;
    }

    @Override
    public boolean deleteEntity(String bucketName, String keyName) {
        LOG.info("Deletes the specified object " + keyName + " in the specified bucket " + bucketName);
        try {
            amazonS3Client.deleteObject(bucketName, keyName);
            return true;
        } catch (AmazonServiceException ase) {
            LOG.warn(ase.getMessage(), ase);
        } catch (AmazonClientException ace) {
            LOG.warn(ace.getMessage(), ace);
        }
        return false;
    }

    @Override
    public boolean deleteEntities(String bucketName) {
        LOG.info("Deletes multiple objects in a bucket " + bucketName + " from Amazon S3");
        List<S3ObjectSummary> s3ObjectSummaries = findEntityByBucket(bucketName);
        if (s3ObjectSummaries == null || s3ObjectSummaries.isEmpty()) {
            return false;
        }

        // Provide a list of object keys and versions.
        List<KeyVersion> keyVersions = new ArrayList<KeyVersion>();
        for (S3ObjectSummary s3ObjectSummary : s3ObjectSummaries) {
            keyVersions.add(new KeyVersion(s3ObjectSummary.getKey()));
        }

        try {
            DeleteObjectsRequest deleteObjectsRequest = new DeleteObjectsRequest(bucketName).withKeys(keyVersions);
            DeleteObjectsResult deleteObjectsResult = amazonS3Client.deleteObjects(deleteObjectsRequest);
            if (deleteObjectsResult != null) {
                LOG.info("Successfully deleted all the " + deleteObjectsResult.getDeletedObjects().size()
                        + " items.\n");
                return true;
            }
        } catch (AmazonServiceException ase) {
            LOG.warn(ase.getMessage(), ase);
        } catch (AmazonClientException ace) {
            LOG.warn(ace.getMessage(), ace);
        }
        return false;
    }

    @Override
    public boolean publicEntity(String bucketName, String keyName) {
        LOG.info("Sets the CannedAccessControlList for the specified object " + keyName
                + " in Amazon S3 using one of the pre-configured CannedAccessControlLists");

        try {
            amazonS3Client.setObjectAcl(bucketName, keyName, CannedAccessControlList.PublicRead);
            return true;
        } catch (AmazonServiceException ase) {
            LOG.warn(ase.getMessage(), ase);
        } catch (AmazonClientException ace) {
            LOG.warn(ace.getMessage(), ace);
        }
        return false;
    }

    @Override
    public boolean copyEntity(String sourceBucketName, String sourceKeyName, String destinationBucketName,
            String destinationKeyName) {

        // If target bucket name is null or empty, that mean copy inside current
        // bucket.
        if (StringUtils.isEmpty(destinationBucketName)) {
            destinationBucketName = sourceBucketName;
        }

        LOG.info("Copies a source object " + sourceKeyName + " from a source bucket " + sourceBucketName
                + " to a new destination bucket " + destinationBucketName + " with specified key "
                + destinationKeyName + " in Amazon S3");

        try {
            CopyObjectRequest copyObjectRequest = new CopyObjectRequest(sourceBucketName, sourceKeyName,
                    destinationBucketName, destinationKeyName);
            CopyObjectResult copyObjectResult = amazonS3Client.copyObject(copyObjectRequest);
            if (copyObjectResult != null) {
                LOG.info(
                        "A CopyObjectResult object containing the information returned by Amazon S3 about the newly created object: "
                                + copyObjectResult);
                return true;
            }
        } catch (AmazonServiceException ase) {
            LOG.warn(ase.getMessage(), ase);
        } catch (AmazonClientException ace) {
            LOG.warn(ace.getMessage(), ace);
        }
        return false;
    }

    @Override
    public boolean isPublicEntity(String bucketName, String keyName) {
        LOG.info("Gets the AccessControlList (ACL) for the specified object " + keyName
                + " in the specified bucket " + bucketName);

        final String GROUPS_USERS = "http://acs.amazonaws.com/groups/global/AllUsers";
        try {
            AccessControlList accessControlList = amazonS3Client.getObjectAcl(bucketName, keyName);
            for (Iterator<Grant> iterator = accessControlList.getGrants().iterator(); iterator.hasNext();) {
                Grant grant = iterator.next();
                if (grant.getPermission().equals(Permission.Read)
                        && grant.getGrantee().getIdentifier().equals(GROUPS_USERS)) {
                    return true;
                }
            }
        } catch (AmazonServiceException ase) {
            LOG.warn(ase.getMessage(), ase);
        } catch (AmazonClientException ace) {
            LOG.warn(ace.getMessage(), ace);
        }
        return false;
    }

    @Override
    public boolean downloadEntity(String bucketName, String keyNotAvailable, File destinationFile) {
        LOG.info("Gets the object metadata for the object stored in Amazon S3 under the specified bucket "
                + bucketName + " and key " + keyNotAvailable
                + ", and saves the object contents to the specified file " + destinationFile);
        try {
            ObjectMetadata objectMetadata = amazonS3Client
                    .getObject(new GetObjectRequest(bucketName, keyNotAvailable), destinationFile);
            if (objectMetadata != null) {
                return true;
            }
        } catch (AmazonServiceException ase) {
            LOG.warn(ase.getMessage(), ase);
        } catch (AmazonClientException ace) {
            LOG.warn(ace.getMessage(), ace);
        }
        return false;
    }

    @Override
    public InputStream downloadEntity(String bucketName, String keyName) {
        LOG.info("Gets the object stored in Amazon S3 under the specified bucket " + bucketName + " and key "
                + keyName);
        try {
            S3Object s3Object = amazonS3Client.getObject(bucketName, keyName);
            if (s3Object != null) {
                return s3Object.getObjectContent();
            }
        } catch (AmazonServiceException ase) {
            LOG.warn(ase.getMessage(), ase);
        } catch (AmazonClientException ace) {
            LOG.warn(ace.getMessage(), ace);
        }
        return null;
    }

    @Override
    public S3Object findEntityByUniqueKey(String bucketName, String keyName) {
        if (StringUtils.isEmpty(keyName)) {
            return null;
        }

        LOG.info("Gets the object stored in Amazon S3 under the specified bucket " + bucketName + " and key "
                + keyName);
        try {
            return amazonS3Client.getObject(bucketName, keyName);
        } catch (AmazonServiceException ase) {
            LOG.warn(ase.getMessage(), ase);
        } catch (AmazonClientException ace) {
            LOG.warn(ace.getMessage(), ace);
        }
        return null;
    }

    @Override
    public List<S3ObjectSummary> findEntityByBucket(String bucketName) {
        LOG.info("Returns a list of summary information about the objects in the specified buckets " + bucketName);

        List<S3ObjectSummary> objectSummaries = new ArrayList<S3ObjectSummary>();
        ObjectListing objectListing;
        try {
            do {
                objectListing = amazonS3Client.listObjects(bucketName);
                for (final S3ObjectSummary objectSummary : objectListing.getObjectSummaries()) {
                    objectSummaries.add(objectSummary);
                }
                objectListing = amazonS3Client.listNextBatchOfObjects(objectListing);
            } while (objectListing.isTruncated());

        } catch (AmazonServiceException ase) {
            LOG.error("Caught an AmazonServiceException, " + "which means your request made it "
                    + "to Amazon S3, but was rejected with an error response " + "for some reason.", ase);
        } catch (AmazonClientException ace) {
            LOG.error("Caught an AmazonClientException, " + "which means the client encountered "
                    + "an internal error while trying to communicate" + " with S3, "
                    + "such as not being able to access the network.", ace);
        }

        return objectSummaries;
    }

    @Override
    public List<S3ObjectSummary> findEntityByPrefixKey(String bucketName, String prefixKey) {
        LOG.info("Returns a list of summary information about the objects in the specified bucket " + bucketName
                + " for the prefix " + prefixKey);

        List<S3ObjectSummary> objectSummaries = new ArrayList<S3ObjectSummary>();
        ListObjectsRequest listObjectsRequest = new ListObjectsRequest().withBucketName(bucketName)
                .withPrefix(prefixKey);
        ObjectListing objectListing;

        try {
            do {
                objectListing = amazonS3Client.listObjects(listObjectsRequest);
                for (final S3ObjectSummary objectSummary : objectListing.getObjectSummaries()) {
                    objectSummaries.add(objectSummary);
                }
                listObjectsRequest.setMarker(objectListing.getNextMarker());
            } while (objectListing.isTruncated());
            LOG.info("Found " + objectSummaries.size() + " objects in the specified bucket " + bucketName
                    + " for the prefix " + prefixKey);
        } catch (AmazonServiceException ase) {
            LOG.error("Caught an AmazonServiceException, " + "which means your request made it "
                    + "to Amazon S3, but was rejected with an error response " + "for some reason.", ase);
        } catch (AmazonClientException ace) {
            LOG.error("Caught an AmazonClientException, " + "which means the client encountered "
                    + "an internal error while trying to communicate" + " with S3, "
                    + "such as not being able to access the network.", ace);
        }

        return objectSummaries;
    }

}