net.solarnetwork.node.backup.s3.SdkS3Client.java Source code

Java tutorial

Introduction

Here is the source code for net.solarnetwork.node.backup.s3.SdkS3Client.java

Source

/* ==================================================================
 * SdkS3Client.java - 3/10/2017 2:11:41 PM
 * 
 * Copyright 2017 SolarNetwork.net Dev Team
 * 
 * This program is free software; you can redistribute it and/or 
 * modify it under the terms of the GNU General Public License as 
 * published by the Free Software Foundation; either version 2 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 
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License 
 * along with this program; if not, write to the Free Software 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
 * 02111-1307 USA
 * ==================================================================
 */

package net.solarnetwork.node.backup.s3;

import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.DeleteObjectsRequest;
import com.amazonaws.services.s3.model.DeleteObjectsRequest.KeyVersion;
import com.amazonaws.services.s3.model.ListObjectsV2Request;
import com.amazonaws.services.s3.model.ListObjectsV2Result;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.s3.model.S3ObjectSummary;
import net.solarnetwork.node.RemoteServiceException;

/**
 * {@link S3Client} using the AWS SDK.
 * 
 * @author matt
 * @version 1.0
 */
public class SdkS3Client implements S3Client {

    private String bucketName;
    private String regionName = Regions.US_WEST_2.getName();
    private int maximumKeysPerRequest = 500;
    private AWSCredentialsProvider credentialsProvider;

    private AmazonS3 s3Client;

    private final Logger log = LoggerFactory.getLogger(getClass());

    private synchronized AmazonS3 getClient() {
        AmazonS3 result = s3Client;
        if (result == null) {
            result = AmazonS3ClientBuilder.standard().withCredentials(credentialsProvider).withRegion(regionName)
                    .build();
            s3Client = result;
        }
        return result;
    }

    @Override
    public boolean isConfigured() {
        return (bucketName != null && bucketName.length() > 0 && regionName != null && regionName.length() > 0
                && credentialsProvider != null);
    }

    @Override
    public Set<S3ObjectReference> listObjects(String prefix) throws IOException {
        AmazonS3 client = getClient();
        Set<S3ObjectReference> result = new LinkedHashSet<>(100);
        try {
            final ListObjectsV2Request req = new ListObjectsV2Request();
            req.setBucketName(bucketName);
            req.setMaxKeys(maximumKeysPerRequest);
            req.setPrefix(prefix);
            ListObjectsV2Result listResult;
            do {
                listResult = client.listObjectsV2(req);

                for (S3ObjectSummary objectSummary : listResult.getObjectSummaries()) {
                    result.add(new S3ObjectReference(objectSummary.getKey(), objectSummary.getSize(),
                            objectSummary.getLastModified()));
                }
                req.setContinuationToken(listResult.getNextContinuationToken());
            } while (listResult.isTruncated() == true);

        } catch (AmazonServiceException e) {
            log.warn("AWS error: {}; HTTP code {}; AWS code {}; type {}; request ID {}", e.getMessage(),
                    e.getStatusCode(), e.getErrorCode(), e.getErrorType(), e.getRequestId());
            throw new RemoteServiceException("Error listing S3 objects at " + prefix, e);
        } catch (AmazonClientException e) {
            log.debug("Error communicating with AWS: {}", e.getMessage());
            throw new IOException("Error communicating with AWS", e);
        }
        return result;
    }

    @Override
    public String getObjectAsString(String key) throws IOException {
        AmazonS3 client = getClient();
        try {
            return client.getObjectAsString(bucketName, key);
        } catch (AmazonServiceException e) {
            log.warn("AWS error: {}; HTTP code {}; AWS code {}; type {}; request ID {}", e.getMessage(),
                    e.getStatusCode(), e.getErrorCode(), e.getErrorType(), e.getRequestId());
            throw new RemoteServiceException("Error getting S3 object at " + key, e);
        } catch (AmazonClientException e) {
            log.debug("Error communicating with AWS: {}", e.getMessage());
            throw new IOException("Error communicating with AWS", e);
        }
    }

    @Override
    public S3Object getObject(String key) throws IOException {
        AmazonS3 client = getClient();
        try {
            return client.getObject(bucketName, key);
        } catch (AmazonServiceException e) {
            log.warn("AWS error: {}; HTTP code {}; AWS code {}; type {}; request ID {}", e.getMessage(),
                    e.getStatusCode(), e.getErrorCode(), e.getErrorType(), e.getRequestId());
            throw new RemoteServiceException("Error getting S3 object at " + key, e);
        } catch (AmazonClientException e) {
            log.debug("Error communicating with AWS: {}", e.getMessage());
            throw new IOException("Error communicating with AWS", e);
        }
    }

    @Override
    public S3ObjectReference putObject(String key, InputStream in, ObjectMetadata objectMetadata)
            throws IOException {
        AmazonS3 client = getClient();
        try {
            PutObjectRequest req = new PutObjectRequest(bucketName, key, in, objectMetadata);
            client.putObject(req);
            return new S3ObjectReference(key, objectMetadata.getContentLength(), objectMetadata.getLastModified());
        } catch (AmazonServiceException e) {
            log.warn("AWS error: {}; HTTP code {}; AWS code {}; type {}; request ID {}", e.getMessage(),
                    e.getStatusCode(), e.getErrorCode(), e.getErrorType(), e.getRequestId());
            throw new RemoteServiceException("Error putting S3 object at " + key, e);
        } catch (AmazonClientException e) {
            log.debug("Error communicating with AWS: {}", e.getMessage());
            throw new IOException("Error communicating with AWS", e);
        }
    }

    @Override
    public void deleteObjects(Set<String> keys) throws IOException {
        AmazonS3 client = getClient();
        try {
            DeleteObjectsRequest req = new DeleteObjectsRequest(bucketName)
                    .withKeys(keys.stream().map(k -> new KeyVersion(k)).collect(Collectors.toList()));
            client.deleteObjects(req);
        } catch (AmazonServiceException e) {
            log.warn("AWS error: {}; HTTP code {}; AWS code {}; type {}; request ID {}", e.getMessage(),
                    e.getStatusCode(), e.getErrorCode(), e.getErrorType(), e.getRequestId());
            throw new RemoteServiceException("Error deleting S3 objects " + keys, e);
        } catch (AmazonClientException e) {
            log.debug("Error communicating with AWS: {}", e.getMessage());
            throw new IOException("Error communicating with AWS", e);
        }
    }

    /**
     * Set the bucket name to connect to.
     * 
     * @param bucketName
     *        the bucketName to set
     */
    public void setBucketName(String bucketName) {
        this.bucketName = bucketName;
    }

    /**
     * Set the AWS region to use.
     * 
     * @param regionName
     *        the region name to set; defaults to us-west-2
     */
    public void setRegionName(String regionName) {
        this.regionName = regionName;
    }

    /**
     * Set the maximum number of S3 object keys to request in one request.
     * 
     * @param maximumKeysPerRequest
     *        the maximum to set
     */
    public void setMaximumKeysPerRequest(int maximumKeysPerRequest) {
        this.maximumKeysPerRequest = maximumKeysPerRequest;
    }

    /**
     * Set the credentials provider to authenticate with.
     * 
     * @param credentialsProvider
     *        the provider to set
     */
    public void setCredentialsProvider(AWSCredentialsProvider credentialsProvider) {
        this.credentialsProvider = credentialsProvider;
    }

}