public Copy copy(final CopyObjectRequest copyObjectRequest, final AmazonS3 srcS3,
                     final TransferStateChangeListener stateChangeListener) throws
                                                                            AmazonServiceException,
                                                                            AmazonClientException {
        assertNotObjectLambdaArn(copyObjectRequest.getDestinationBucketName(), "copy");
        assertNotObjectLambdaArn(copyObjectRequest.getSourceBucketName(), "copy");

        appendSingleObjectUserAgent(copyObjectRequest);

        assertParameterNotNull(copyObjectRequest.getSourceBucketName(),
                               "The source bucket name must be specified when a copy request is initiated.");
        assertParameterNotNull(copyObjectRequest.getSourceKey(),
                               "The source object key must be specified when a copy request is initiated.");
        assertParameterNotNull(copyObjectRequest.getDestinationBucketName(),
                               "The destination bucket name must be specified when a copy request is initiated.");
        assertParameterNotNull(copyObjectRequest.getDestinationKey(),
                               "The destination object key must be specified when a copy request is initiated.");
        assertParameterNotNull(srcS3, "The srcS3 parameter is mandatory");

        String description =
                "Copying object from " + copyObjectRequest.getSourceBucketName() + "/" +
                copyObjectRequest.getSourceKey() + " to " +
                copyObjectRequest.getDestinationBucketName() + "/" +
                copyObjectRequest.getDestinationKey();

        GetObjectMetadataRequest getObjectMetadataRequest = new GetObjectMetadataRequest(
                copyObjectRequest.getSourceBucketName(), copyObjectRequest.getSourceKey())
                .withSSECustomerKey(copyObjectRequest.getSourceSSECustomerKey())
                .withRequesterPays(copyObjectRequest.isRequesterPays())
                .withVersionId(copyObjectRequest.getSourceVersionId())
                .withRequestCredentialsProvider(copyObjectRequest.getRequestCredentialsProvider());

        ObjectMetadata metadata = srcS3.getObjectMetadata(getObjectMetadataRequest);

        TransferProgress transferProgress = new TransferProgress();
        transferProgress.setTotalBytesToTransfer(metadata.getContentLength());

        ProgressListenerChain listenerChain = new ProgressListenerChain(
                new TransferProgressUpdatingListener(transferProgress));
        CopyImpl copy = new CopyImpl(description, transferProgress, listenerChain,
                                     stateChangeListener);
        CopyCallable copyCallable = new CopyCallable(this, executorService, copy, copyObjectRequest,
                                                     metadata, listenerChain);
        CopyMonitor watcher = CopyMonitor
                .create(this, copy, executorService, copyCallable, copyObjectRequest,
                        listenerChain);
        copy.setMonitor(watcher);
        return copy;
    }
<p>
Schedules a new transfer to copy data from one Amazon S3 location to
another Amazon S3 location. This method is non-blocking and returns
immediately (i.e. before the copy has finished).
</p>
<p>
Note: You need to use this method if the {@link TransferManager} is created with
a regional S3 client and the source & destination buckets are in different regions.
</p>
<p>
<code>TransferManager</code> doesn't support copying of encrypted objects
whose encryption materials are stored in an instruction file.
</p>
<p>
Use the returned <code>Copy</code> object to check if the copy is
complete.
</p>
<p>
If resources are available, the copy request will begin immediately.
Otherwise, the copy is scheduled and started as soon as resources become
available.
</p>

@param copyObjectRequest   The request containing all the parameters for the copy.
@param srcS3               An AmazonS3 client constructed for the region in which the source
                           object's bucket is located.
@param stateChangeListener The transfer state change listener to monitor the copy request
@return A new <code>Copy</code> object to use to check the state of the
copy request being processed.
@throws AmazonClientException  If any errors are encountered in the client while making the
                               request or handling the response.
@throws AmazonServiceException If any errors occurred in Amazon S3 while processing the
                               request.
aws-java-sdk-s3/src/main/java/com/amazonaws/services/s3/transfer/TransferManager.java