final String destinationBucket, final String destinationObject, CopyObjectOptions... nullableOptions) {
final CopyObjectOptions options = (nullableOptions.length == 0) ? new CopyObjectOptions() : nullableOptions[0];
ConcurrentMap<String, Blob> source = containerToBlobs.get(sourceBucket);
ConcurrentMap<String, Blob> dest = containerToBlobs.get(destinationBucket);
if (source.containsKey(sourceObject)) {
Blob object = source.get(sourceObject);
if (options.getIfMatch() != null) {
if (!object.getMetadata().getETag().equals(options.getIfMatch()))
return immediateFailedFuture(LocalAsyncBlobStore.returnResponseException(412));
}
if (options.getIfNoneMatch() != null) {
if (object.getMetadata().getETag().equals(options.getIfNoneMatch()))
return immediateFailedFuture(LocalAsyncBlobStore.returnResponseException(412));
}
if (options.getIfModifiedSince() != null) {
Date modifiedSince = dateService.rfc822DateParse(options.getIfModifiedSince());
if (modifiedSince.after(object.getMetadata().getLastModified()))
return immediateFailedFuture(LocalAsyncBlobStore.returnResponseException(412));
}
if (options.getIfUnmodifiedSince() != null) {
Date unmodifiedSince = dateService.rfc822DateParse(options.getIfUnmodifiedSince());
if (unmodifiedSince.before(object.getMetadata().getLastModified()))
return immediateFailedFuture(LocalAsyncBlobStore.returnResponseException(412));
}
Blob sourceS3 = source.get(sourceObject);
MutableBlobMetadata newMd = BlobStoreUtils.copy(sourceS3.getMetadata(), destinationObject);
if (options.getAcl() != null)
keyToAcl.put(destinationBucket + "/" + destinationObject, options.getAcl());
newMd.setLastModified(new Date());
Blob newBlob = blobProvider.create(newMd);
newBlob.setPayload(sourceS3.getPayload());
dest.put(destinationObject, newBlob);
return immediateFuture((ObjectMetadata) blob2ObjectMetadata.apply(BlobStoreUtils.copy(newMd)));
}
return immediateFailedFuture(new KeyNotFoundException(sourceBucket, sourceObject, sourceBucket + "/"
+ sourceObject));