ProgressListener progressListener = getObjectRequest.getGeneralProgressListener();
ProgressListenerCallbackExecutor progressListenerCallbackExecutor = ProgressListenerCallbackExecutor
.wrapListener(progressListener);
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 input = 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.
input = new ServiceClientHolderInputStream(input, this);
// If someone is interested in progress updates, wrap the input
// stream in a filter that will trigger progress reports.
if (progressListenerCallbackExecutor != null) {
@SuppressWarnings("resource")
ProgressReportingInputStream progressReportingInputStream = new ProgressReportingInputStream(
input, progressListenerCallbackExecutor);
progressReportingInputStream.setFireCompletedEvent(true);
input = progressReportingInputStream;
fireProgressEvent(progressListenerCallbackExecutor, ProgressEvent.STARTED_EVENT_CODE);
}
// 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 (getObjectRequest.getRange() == null
&& System.getProperty("com.amazonaws.services.s3.disableGetObjectMD5Validation") == null) {
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");
input = new DigestValidationInputStream(input, 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
input = new LengthCheckInputStream(input,
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(input, httpRequest, false));
return s3Object;
} catch (AmazonS3Exception ase) {
/*
* If the request failed because one of the specified constraints