request.getHeaders().remove(Headers.CONTENT_LENGTH);
signRequest(request, HttpMethodName.PUT, destinationBucketName, destinationKey);
HttpRequest httpRequest = convertToHttpRequest(request, HttpMethodName.PUT);
CopyObjectResultHandler copyObjectResultHandler = null;
try {
// TODO: Should we move some more of this logic into CopyObjectResponseHandler?
// For example, detecting the different failure modes?
CopyObjectResponseHandler responseHandler = new CopyObjectResponseHandler();
copyObjectResultHandler =
(CopyObjectResultHandler)client.execute(httpRequest, responseHandler, errorResponseHandler);
} catch (AmazonS3Exception ase) {
/*
* If the request failed because one of the specified constraints
* was not met (ex: matching ETag, modified since date, etc.), then
* return null, so that users don't have to wrap their code in
* try/catch blocks and check for this status code if they want to
* use constraints.
*/
if (ase.getStatusCode() == Constants.FAILED_PRECONDITION_STATUS_CODE) {
return null;
}
throw ase;
}
/*
* CopyObject has two failure modes:
* 1 - An HTTP error code is returned and the error is processed like any
* other error response.
* 2 - An HTTP 200 OK code is returned, but the response content contains
* an XML error response.
*
* This makes it very difficult for the client runtime to cleanly detect
* this case and handle it like any other error response. We could
* extend the runtime to have a more flexible/customizable definition of
* success/error (per request), but it's probably overkill for this
* one special case.
*/
if (copyObjectResultHandler.getErrorCode() != null) {
String errorCode = copyObjectResultHandler.getErrorCode();
String errorMessage = copyObjectResultHandler.getErrorMessage();
String requestId = copyObjectResultHandler.getErrorRequestId();
String hostId = copyObjectResultHandler.getErrorHostId();
AmazonS3Exception ase = new AmazonS3Exception(errorMessage);
ase.setErrorCode(errorCode);
ase.setErrorType(ErrorType.Service);
ase.setRequestId(requestId);
ase.setExtendedRequestId(hostId);
ase.setServiceName(request.getServiceName());
ase.setStatusCode(200);
throw ase;
}
// TODO: Might be nice to create this in our custom CopyObjectResponseHandler
CopyObjectResult copyObjectResult = new CopyObjectResult();
copyObjectResult.setETag(copyObjectResultHandler.getETag());
copyObjectResult.setLastModifiedDate(
copyObjectResultHandler.getLastModified());
copyObjectResult.setVersionId(copyObjectResultHandler.getVersionId());
return copyObjectResult;
}