}
final ObjectMetadata objectMetadata = s3.getObjectMetadata(getObjectMetadataRequest);
final StartDownloadLock startDownloadLock = new StartDownloadLock();
// We still pass the unfiltered listener chain into DownloadImpl
final DownloadImpl download = new DownloadImpl(description,
transferProgress, listenerChain, null, stateListener,
getObjectRequest, file);
long contentLength = objectMetadata.getContentLength();
long startingByte = 0;
long lastByte = contentLength;
if (getObjectRequest.getRange() != null
&& getObjectRequest.getRange().length == 2) {
startingByte = getObjectRequest.getRange()[0];
lastByte = getObjectRequest.getRange()[1];
}
if (resumeExistingDownload) {
if (file.exists()) {
long numberOfBytesRead = file.length();
startingByte = startingByte + numberOfBytesRead;
getObjectRequest.setRange(startingByte, lastByte);
}
}
contentLength = lastByte - startingByte;
if (contentLength < 0) {
throw new IllegalArgumentException(
"Unable to determine the range for download operation.");
}
transferProgress.setTotalBytesToTransfer(contentLength);
Future<?> future = threadPool.submit(new Callable<Object>() {
@Override
public Object call() throws Exception {
try {
synchronized (startDownloadLock) {
if ( !startDownloadLock.downloadReady ) {
try {
startDownloadLock.wait();
} catch ( InterruptedException e ) {
throw new AmazonClientException("Couldn't wait for setting future into the monitor");
}
}
}
download.setState(TransferState.InProgress);
S3Object s3Object = ServiceUtils.retryableDownloadS3ObjectToFile(file, new ServiceUtils.RetryableS3DownloadTask() {
@Override
public S3Object getS3ObjectStream() {
S3Object s3Object = s3.getObject(getObjectRequest);
download.setS3Object(s3Object);
return s3Object;
}
@Override
public boolean needIntegrityCheck() {
// Don't perform the integrity check if the stream data is wrapped
// in a decryption stream, or if we're only looking at a range of
// the data, since otherwise the checksum won't match up.
boolean performIntegrityCheck = true;
if (getObjectRequest.getRange() != null) performIntegrityCheck = false;
if (s3 instanceof AmazonS3EncryptionClient) performIntegrityCheck = false;
return performIntegrityCheck;
}
}, resumeExistingDownload);
if (s3Object == null) {
download.setState(TransferState.Canceled);
download.setMonitor(new DownloadMonitor(download, null));
return download;
}
download.setState(TransferState.Completed);
return true;
} catch (Exception e) {
// Downloads aren't allowed to move from canceled to failed
if (download.getState() != TransferState.Canceled) {
download.setState(TransferState.Failed);
}
throw e;
}
}
});
download.setMonitor(new DownloadMonitor(download, future));
synchronized (startDownloadLock) {
startDownloadLock.downloadReady = true;
startDownloadLock.notify();
}
return download;