public function copyObject(
        $sourceBucketName,
        $sourceKey,
        $targetBucketName,
        $targetKey,
        $options = array()
    ) {
        if (empty($sourceBucketName)) {
            throw new \InvalidArgumentException(
                '$sourceBucketName should not be empty or null.'
            );
        }
        if (empty($sourceKey)) {
            throw new \InvalidArgumentException(
                '$sourceKey should not be empty or null.'
            );
        }
        if (empty($targetBucketName)) {
            throw new \InvalidArgumentException(
                '$targetBucketName should not be empty or null.'
            );
        }
        if (empty($targetKey)) {
            throw new \InvalidArgumentException(
                '$targetKey should not be empty or null.'
            );
        }

        list($config, $userMetadata, $etag, $storageClass) = $this->parseOptions(
            $options,
            BosOptions::CONFIG,
            BosOptions::USER_METADATA,
            BosOptions::ETAG,
            BosOptions::STORAGE_CLASS
        );

        $headers = array();

        $headers[HttpHeaders::BCE_COPY_SOURCE] =
            HttpUtils::urlEncodeExceptSlash(
                sprintf("/%s/%s", $sourceBucketName, $sourceKey)
            );
        if ($etag !== null) {
            $etag = trim($etag, '"');
            $headers[HttpHeaders::BCE_COPY_SOURCE_IF_MATCH] = '"' . $etag . '"';
        }
        if ($userMetadata === null) {
            $headers[HttpHeaders::BCE_COPY_METADATA_DIRECTIVE] = 'copy';
        } else {
            $headers[HttpHeaders::BCE_COPY_METADATA_DIRECTIVE] = 'replace';
            $this->populateRequestHeadersWithUserMetadata(
                $headers,
                $userMetadata
            );
        }
        if ($storageClass !== null) {
            $headers[HttpHeaders::BCE_STORAGE_CLASS] = $storageClass;
        } else {
            $headers[HttpHeaders::BCE_STORAGE_CLASS] = StorageClass::STANDARD;
        }

        return $this->sendRequest(
            HttpMethod::PUT,
            array(
                BosOptions::CONFIG => $config,
                'bucket_name' => $targetBucketName,
                'key' => $targetKey,
                'headers' => $headers,
            )
        );
    }