/* * Copyright 2014-2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. * A copy of the License is located at * * http://aws.amazon.com/apache2.0 * * or in the "license" file accompanying this file. This file is distributed * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing * permissions and limitations under the License. */ package com.amazonaws.services.s3; import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import org.apache.commons.logging.LogFactory; import com.amazonaws.AmazonWebServiceRequest; import com.amazonaws.services.s3.internal.MultiFileOutputStream; import com.amazonaws.services.s3.internal.PartCreationEvent; import com.amazonaws.services.s3.internal.S3DirectSpi; import com.amazonaws.services.s3.model.AbortMultipartUploadRequest; import com.amazonaws.services.s3.model.CompleteMultipartUploadRequest; import com.amazonaws.services.s3.model.CompleteMultipartUploadResult; import com.amazonaws.services.s3.model.EncryptedInitiateMultipartUploadRequest; import com.amazonaws.services.s3.model.InitiateMultipartUploadRequest; import com.amazonaws.services.s3.model.InitiateMultipartUploadResult; import com.amazonaws.services.s3.model.PartETag; import com.amazonaws.services.s3.model.UploadObjectRequest; import com.amazonaws.services.s3.model.UploadPartRequest; import com.amazonaws.services.s3.model.UploadPartResult; /** * An observer that gets notified of ciphertext file creation for the purpose of * pipelined parallel multi-part uploads of encrypted data to S3. This observer * is responsible for uploading the files to S3 via multi-part upload, including * the multi-part upload initiation, individual part uploads, and multi-part * upload completion. *
* This observer is designed for extension so that custom behavior can be
* provided. A customer observer can be configured via
* {@link UploadObjectRequest#withUploadObjectObserver(UploadObjectObserver)}.
*
* @see UploadObjectRequest
*/
public class UploadObjectObserver {
private final List
* Implementation of this method should never block.
*
* @param req
* the upload object request
* @param s3direct
* used to perform non-encrypting s3 operation via the current
* instance of s3 (encryption) client
* @param s3
* the current instance of s3 (encryption) client
* @param es
* the executor service to be used for concurrent uploads
* @return this object
*/
public UploadObjectObserver init(UploadObjectRequest req,
S3DirectSpi s3direct, AmazonS3 s3, ExecutorService es) {
this.req = req;
this.s3direct = s3direct;
this.s3 = s3;
this.es = es;
return this;
}
protected InitiateMultipartUploadRequest newInitiateMultipartUploadRequest(
UploadObjectRequest req) {
return new EncryptedInitiateMultipartUploadRequest(
req.getBucketName(), req.getKey(), req.getMetadata())
.withMaterialsDescription(req.getMaterialsDescription())
.withRedirectLocation(req.getRedirectLocation())
.withSSEAwsKeyManagementParams(req.getSSEAwsKeyManagementParams())
.withSSECustomerKey(req.getSSECustomerKey())
.withStorageClass(req.getStorageClass())
.withAccessControlList(req.getAccessControlList())
.withCannedACL(req.getCannedAcl())
.withGeneralProgressListener(req.getGeneralProgressListener())
.withRequestMetricCollector(req.getRequestMetricCollector())
.withRequestCredentialsProvider(req.getRequestCredentialsProvider())
;
}
/**
* Notified from
* {@link AmazonS3EncryptionClient#uploadObject(UploadObjectRequest)} to
* initiate a multi-part upload.
*
* @param req
* the upload object request
* @return the initiated multi-part uploadId
*/
public String onUploadInitiation(UploadObjectRequest req) {
InitiateMultipartUploadResult res =
s3.initiateMultipartUpload(newInitiateMultipartUploadRequest(req));
return this.uploadId = res.getUploadId();
}
/**
* Notified from {@link MultiFileOutputStream#fos()} when a part ready for
* upload has been successfully created on disk. By default, this method
* performs the following:
*
* To enable parallel uploads, implementation of this method should never
* block.
*
* @param event
* to represent the completion of a ciphertext file creation
* which is ready for multipart upload to S3.
*/
public void onPartCreate(PartCreationEvent event) {
final File part = event.getPart();
final UploadPartRequest reqUploadPart =
newUploadPartRequest(event, part);
final OnFileDelete fileDeleteObserver = event.getFileDeleteObserver();
futures.add(es.submit(new CallableAmazonS3EncryptionClient
.
*
*
* S3DirectSpi
instance initialized via
* {@link #init(UploadObjectRequest, S3DirectSpi, AmazonS3, ExecutorService)}
*/
protected S3DirectSpi getS3DirectSpi() {
return s3direct;
}
/**
* Returns the AmazonS3
instance initialized via
* {@link #init(UploadObjectRequest, S3DirectSpi, AmazonS3, ExecutorService)}
*/
protected AmazonS3 getAmazonS3() {
return s3;
}
/**
* Returns the ExecutorService
instance initialized via
* {@link #init(UploadObjectRequest, S3DirectSpi, AmazonS3, ExecutorService)}
*/
protected ExecutorService getExecutorService() {
return es;
}
}