populateSseCpkRequestParameters(request, getObjectRequest.getSSECustomerKey());
final ProgressListener listener = getObjectRequest.getGeneralProgressListener();
publishProgress(listener, ProgressEventType.TRANSFER_STARTED_EVENT);
try {
S3Object s3Object = invoke(request, new S3ObjectResponseHandler(),
getObjectRequest.getBucketName(), getObjectRequest.getKey());
/*
* TODO: For now, it's easiest to set there here in the client, but
* we could push this back into the response handler with a
* little more work.
*/
s3Object.setBucketName(getObjectRequest.getBucketName());
s3Object.setKey(getObjectRequest.getKey());
InputStream is = s3Object.getObjectContent();
HttpRequestBase httpRequest = s3Object.getObjectContent().getHttpRequest();
// Hold a reference to this client while the InputStream is still
// around - otherwise a finalizer in the HttpClient may reset the
// underlying TCP connection out from under us.
is = new ServiceClientHolderInputStream(is, this);
// used trigger a tranfer complete event when the stream is entirely consumed
ProgressInputStream progressInputStream =
new ProgressInputStream(is, listener) {
@Override protected void onEOF() {
publishProgress(getListener(), ProgressEventType.TRANSFER_COMPLETED_EVENT);
}
};
is = progressInputStream;
// The Etag header contains a server-side MD5 of the object. If
// we're downloading the whole object, by default we wrap the
// stream in a validator that calculates an MD5 of the downloaded
// bytes and complains if what we received doesn't match the Etag.
if ( !skipContentMd5IntegrityCheck(getObjectRequest) ) {
byte[] serverSideHash = null;
String etag = s3Object.getObjectMetadata().getETag();
if (etag != null && ServiceUtils.isMultipartUploadETag(etag) == false) {
serverSideHash = BinaryUtils.fromHex(s3Object.getObjectMetadata().getETag());
try {
// No content length check is performed when the
// MD5 check is enabled, since a correct MD5 check would
// imply a correct content length.
MessageDigest digest = MessageDigest.getInstance("MD5");
is = new DigestValidationInputStream(is, digest, serverSideHash);
} catch (NoSuchAlgorithmException e) {
log.warn("No MD5 digest algorithm available. Unable to calculate "
+ "checksum and verify data integrity.", e);
}
}
} else {
// Ensures the data received from S3 has the same length as the
// expected content-length
is = new LengthCheckInputStream(is,
s3Object.getObjectMetadata().getContentLength(), // expected length
INCLUDE_SKIPPED_BYTES); // bytes received from S3 are all included even if skipped
}
// Re-wrap within an S3ObjectInputStream. Explicitly do not collect
// metrics here because we know we're ultimately wrapping another
// S3ObjectInputStream which will take care of that.
s3Object.setObjectContent(new S3ObjectInputStream(is, httpRequest, false));
return s3Object;
} catch (AmazonS3Exception ase) {
/*
* If the request failed because one of the specified constraints