JCLOUDS-871: Azure Copy Blob support

API reference:

http://msdn.microsoft.com/en-us/library/dd894037.aspx
This commit is contained in:
Andrew Gaul 2014-09-06 18:03:23 -07:00
parent 75f6d76f1d
commit 5487400037
6 changed files with 458 additions and 0 deletions

View File

@ -24,6 +24,13 @@ package org.jclouds.azure.storage.reference;
public final class AzureStorageHeaders {
public static final String USER_METADATA_PREFIX = "x-ms-meta-";
public static final String COPY_SOURCE = "x-ms-copy-source";
public static final String COPY_SOURCE_IF_MODIFIED_SINCE = "x-ms-source-if-modified-since";
public static final String COPY_SOURCE_IF_UNMODIFIED_SINCE = "x-ms-source-if-unmodified-since";
public static final String COPY_SOURCE_IF_MATCH = "x-ms-source-if-match";
public static final String COPY_SOURCE_IF_NONE_MATCH = "x-ms-source-if-none-match";
public static final String REQUEST_ID = "x-ms-request-id";
public static final String VERSION = "x-ms-version";

View File

@ -26,6 +26,7 @@ import static org.jclouds.blobstore.BlobStoreFallbacks.NullOnContainerNotFound;
import static org.jclouds.blobstore.BlobStoreFallbacks.NullOnKeyNotFound;
import java.io.Closeable;
import java.net.URI;
import java.util.List;
import java.util.Map;
@ -57,6 +58,7 @@ import org.jclouds.azureblob.functions.ParseBlobFromHeadersAndHttpContent;
import org.jclouds.azureblob.functions.ParseBlobPropertiesFromHeaders;
import org.jclouds.azureblob.functions.ParseContainerPropertiesFromHeaders;
import org.jclouds.azureblob.functions.ParsePublicAccessHeader;
import org.jclouds.azureblob.options.CopyBlobOptions;
import org.jclouds.azureblob.options.CreateContainerOptions;
import org.jclouds.azureblob.options.ListBlobsOptions;
import org.jclouds.azureblob.predicates.validators.BlockIdValidator;
@ -442,4 +444,15 @@ public interface AzureBlobClient extends Closeable {
@PathParam("container") @ParamValidators(ContainerNameValidator.class) String container,
@PathParam("name") String name);
/**
* @throws ContainerNotFoundException if the container is not present.
*/
@Named("CopyBlob")
@PUT
@Path("{toContainer}/{toName}")
@Headers(keys = AzureStorageHeaders.COPY_SOURCE, values = "{copySource}")
void copyBlob(
@PathParam("copySource") URI copySource,
@PathParam("toContainer") @ParamValidators(ContainerNameValidator.class) String toContainer, @PathParam("toName") String toName,
@BinderParam(BindAzureCopyOptionsToRequest.class) CopyBlobOptions options);
}

View File

@ -0,0 +1,70 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.azureblob.binders;
import java.util.Date;
import java.util.Map;
import org.jclouds.azure.storage.reference.AzureStorageHeaders;
import org.jclouds.azureblob.options.CopyBlobOptions;
import org.jclouds.date.DateService;
import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.Binder;
import com.google.common.base.Optional;
/** Binds options to a copyBlob request. */
public class BindAzureCopyOptionsToRequest implements Binder {
private static final DateService dateService = new SimpleDateFormatDateService();
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
HttpRequest.Builder builder = request.toBuilder();
CopyBlobOptions options = (CopyBlobOptions) input;
Optional<Map<String, String>> userMetadata = options.getUserMetadata();
if (userMetadata.isPresent()) {
for (Map.Entry<String, String> entry : userMetadata.get().entrySet()) {
builder.addHeader(AzureStorageHeaders.USER_METADATA_PREFIX + entry.getKey(), entry.getValue());
}
}
Optional<Date> ifModifiedSince = options.getIfModifiedSince();
if (ifModifiedSince.isPresent()) {
builder.addHeader(AzureStorageHeaders.COPY_SOURCE_IF_MODIFIED_SINCE, dateService.rfc822DateFormat(ifModifiedSince.get()));
}
Optional<Date> ifUnmodifiedSince = options.getIfUnmodifiedSince();
if (ifUnmodifiedSince.isPresent()) {
builder.addHeader(AzureStorageHeaders.COPY_SOURCE_IF_UNMODIFIED_SINCE, dateService.rfc822DateFormat(ifUnmodifiedSince.get()));
}
Optional<String> ifMatch = options.getIfMatch();
if (ifMatch.isPresent()) {
builder.addHeader(AzureStorageHeaders.COPY_SOURCE_IF_MATCH, ifMatch.get());
}
Optional<String> ifNoneMatch = options.getIfNoneMatch();
if (ifNoneMatch.isPresent()) {
builder.addHeader(AzureStorageHeaders.COPY_SOURCE_IF_NONE_MATCH, ifNoneMatch.get());
}
return (R) builder.build();
}
}

View File

@ -0,0 +1,109 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.azureblob.options;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Date;
import java.util.Map;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;
public final class CopyBlobOptions {
public static final CopyBlobOptions NONE = CopyBlobOptions.builder().build();
private final Optional<Map<String, String>> userMetadata;
private final Optional<Date> ifModifiedSince;
private final Optional<Date> ifUnmodifiedSince;
private final Optional<String> ifMatch;
private final Optional<String> ifNoneMatch;
private CopyBlobOptions(Map<String, String> userMetadata, Date ifModifiedSince, Date ifUnmodifiedSince,
String ifMatch, String ifNoneMatch) {
this.userMetadata = Optional.fromNullable(userMetadata);
this.ifModifiedSince = Optional.fromNullable(ifModifiedSince);
this.ifUnmodifiedSince = Optional.fromNullable(ifUnmodifiedSince);
this.ifMatch = Optional.fromNullable(ifMatch);
this.ifNoneMatch = Optional.fromNullable(ifNoneMatch);
}
public static Builder builder() {
return new Builder();
}
public Optional<Map<String, String>> getUserMetadata() {
return userMetadata;
}
public Optional<Date> getIfModifiedSince() {
return Optional.fromNullable(ifModifiedSince.isPresent() ? (Date) ifModifiedSince.get().clone() : null);
}
public Optional<Date> getIfUnmodifiedSince() {
return Optional.fromNullable(ifUnmodifiedSince.isPresent() ? (Date) ifUnmodifiedSince.get().clone() : null);
}
public Optional<String> getIfMatch() {
return ifMatch;
}
public Optional<String> getIfNoneMatch() {
return ifNoneMatch;
}
public static class Builder {
private Map<String, String> userMetadata;
private Date ifModifiedSince;
private Date ifUnmodifiedSince;
private String ifMatch;
private String ifNoneMatch;
Builder() {
}
public Builder overrideUserMetadata(Map<String, String> userMetadata) {
this.userMetadata = ImmutableMap.copyOf(checkNotNull(userMetadata, "userMetadata"));
return this;
}
public Builder ifModifiedSince(Date ifModifiedSince) {
this.ifModifiedSince = (Date) checkNotNull(ifModifiedSince, "ifModifiedSince").clone();
return this;
}
public Builder ifUnmodifiedSince(Date ifUnmodifiedSince) {
this.ifUnmodifiedSince = (Date) checkNotNull(ifUnmodifiedSince, "ifUnmodifiedSince").clone();
return this;
}
public Builder ifMatch(String ifMatch) {
this.ifMatch = checkNotNull(ifMatch, "ifMatch");
return this;
}
public Builder ifNoneMatch(String ifNoneMatch) {
this.ifNoneMatch = checkNotNull(ifNoneMatch, "ifNoneMatch");
return this;
}
public CopyBlobOptions build() {
return new CopyBlobOptions(userMetadata, ifModifiedSince, ifUnmodifiedSince, ifMatch, ifNoneMatch);
}
}
}

View File

@ -18,6 +18,7 @@ package org.jclouds.azureblob;
import static com.google.common.io.BaseEncoding.base16;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Fail.failBecauseExceptionWasNotThrown;
import static org.jclouds.azure.storage.options.ListOptions.Builder.includeMetadata;
import static org.jclouds.azureblob.options.CreateContainerOptions.Builder.withMetadata;
import static org.jclouds.azureblob.options.CreateContainerOptions.Builder.withPublicAccess;
@ -29,6 +30,8 @@ import java.lang.reflect.UndeclaredThrowableException;
import java.net.URI;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import org.jclouds.azure.storage.AzureStorageResponseException;
@ -40,14 +43,17 @@ import org.jclouds.azureblob.domain.ContainerProperties;
import org.jclouds.azureblob.domain.ListBlobBlocksResponse;
import org.jclouds.azureblob.domain.ListBlobsResponse;
import org.jclouds.azureblob.domain.PublicAccess;
import org.jclouds.azureblob.options.CopyBlobOptions;
import org.jclouds.azureblob.options.ListBlobsOptions;
import org.jclouds.blobstore.ContainerNotFoundException;
import org.jclouds.blobstore.integration.internal.BaseBlobStoreIntegrationTest;
import org.jclouds.http.HttpResponseException;
import org.jclouds.http.options.GetOptions;
import org.jclouds.io.ByteStreams2;
import org.jclouds.io.Payloads;
import org.jclouds.util.Strings2;
import org.jclouds.util.Throwables2;
import org.jclouds.utils.TestUtils;
import org.testng.annotations.Test;
import com.google.common.base.Charsets;
@ -56,6 +62,7 @@ import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Iterables;
import com.google.common.hash.Hashing;
import com.google.common.io.BaseEncoding;
import com.google.common.io.ByteSource;
@Test(groups = "live", singleThreaded = true)
public class AzureBlobClientLiveTest extends BaseBlobStoreIntegrationTest {
@ -384,4 +391,157 @@ public class AzureBlobClientLiveTest extends BaseBlobStoreIntegrationTest {
client.setPublicAccessForContainer(blockContainer, access);
assertThat(client.getPublicAccessForContainer(blockContainer)).isEqualTo(access);
}
@Test(timeOut = 5 * 60 * 1000, dependsOnMethods = { "testCreateContainer" })
public void testCopyBlob() throws Exception {
ByteSource byteSource = TestUtils.randomByteSource().slice(0, 1024);
// create blob
AzureBlob object = getApi().newBlob();
object.getProperties().setName("from");
object.setPayload(byteSource.read());
getApi().putBlob(privateContainer, object);
// copy blob
URI copySource = view.getSigner().signGetBlob(privateContainer, "from").getEndpoint();
getApi().copyBlob(copySource, privateContainer, "to", CopyBlobOptions.NONE);
// ensure copied blob matches original
AzureBlob getBlob = getApi().getBlob(privateContainer, "to");
assertEquals(ByteStreams2.toByteArrayAndClose(getBlob.getPayload().openStream()), byteSource.read());
assertThat(getBlob.getProperties().getMetadata().isEmpty());
}
@Test(timeOut = 5 * 60 * 1000, dependsOnMethods = { "testCreateContainer" })
public void testCopyBlobReplaceMetadata() throws Exception {
ByteSource byteSource = TestUtils.randomByteSource().slice(0, 1024);
// create blob
AzureBlob object = getApi().newBlob();
object.getProperties().setName("from");
object.setPayload(byteSource.read());
getApi().putBlob(privateContainer, object);
// copy blob
URI copySource = view.getSigner().signGetBlob(privateContainer, "from").getEndpoint();
Map<String, String> newMetadata = ImmutableMap.of("foo", "bar");
getApi().copyBlob(copySource, privateContainer, "to", CopyBlobOptions.builder().overrideUserMetadata(newMetadata).build());
// ensure copied blob matches original
AzureBlob getBlob = getApi().getBlob(privateContainer, "to");
assertEquals(ByteStreams2.toByteArrayAndClose(getBlob.getPayload().openStream()), byteSource.read());
assertThat(getBlob.getProperties().getMetadata()).isEqualTo(newMetadata);
}
@Test(timeOut = 5 * 60 * 1000, dependsOnMethods = { "testCreateContainer" })
public void testCopyBlobIfModifiedSince() throws Exception {
ByteSource byteSource = TestUtils.randomByteSource().slice(0, 1024);
// create blob
AzureBlob object = getApi().newBlob();
object.getProperties().setName("from");
object.setPayload(byteSource.read());
String eTag = getApi().putBlob(privateContainer, object);
long now = System.currentTimeMillis();
Date before = new Date(now - 1000 * 1000);
Date after = new Date(now + 1000 * 1000);
URI copySource = view.getSigner().signGetBlob(privateContainer, "from").getEndpoint();
// failure case
try {
getApi().copyBlob(copySource, privateContainer, "to-if-modified-since", CopyBlobOptions.builder().ifModifiedSince(after).build());
failBecauseExceptionWasNotThrown(AzureStorageResponseException.class);
} catch (AzureStorageResponseException asre) {
assertThat(asre.getResponse().getStatusCode()).as("status code").isEqualTo(412);
}
// success case
getApi().copyBlob(copySource, privateContainer, "to-if-modified-since", CopyBlobOptions.builder().ifModifiedSince(before).build());
AzureBlob getBlob = getApi().getBlob(privateContainer, "to-if-modified-since");
assertEquals(ByteStreams2.toByteArrayAndClose(getBlob.getPayload().openStream()), byteSource.read());
}
@Test(timeOut = 5 * 60 * 1000, dependsOnMethods = { "testCreateContainer" })
public void testCopyBlobIfUnmodifiedSince() throws Exception {
ByteSource byteSource = TestUtils.randomByteSource().slice(0, 1024);
// create blob
AzureBlob object = getApi().newBlob();
object.getProperties().setName("from");
object.setPayload(byteSource.read());
String eTag = getApi().putBlob(privateContainer, object);
long now = System.currentTimeMillis();
Date before = new Date(now - 1000 * 1000);
Date after = new Date(now + 1000 * 1000);
URI copySource = view.getSigner().signGetBlob(privateContainer, "from").getEndpoint();
// failure case
try {
getApi().copyBlob(copySource, privateContainer, "to-if-unmodifed-since", CopyBlobOptions.builder().ifUnmodifiedSince(before).build());
failBecauseExceptionWasNotThrown(AzureStorageResponseException.class);
} catch (AzureStorageResponseException asre) {
assertThat(asre.getResponse().getStatusCode()).as("status code").isEqualTo(412);
}
// success case
getApi().copyBlob(copySource, privateContainer, "to-if-unmodifed-since", CopyBlobOptions.builder().ifUnmodifiedSince(after).build());
AzureBlob getBlob = getApi().getBlob(privateContainer, "to-if-unmodifed-since");
assertEquals(ByteStreams2.toByteArrayAndClose(getBlob.getPayload().openStream()), byteSource.read());
}
@Test(timeOut = 5 * 60 * 1000, dependsOnMethods = { "testCreateContainer" })
public void testCopyBlobIfMatch() throws Exception {
ByteSource byteSource = TestUtils.randomByteSource().slice(0, 1024);
// create blob
AzureBlob object = getApi().newBlob();
object.getProperties().setName("from");
object.setPayload(byteSource.read());
String eTag = getApi().putBlob(privateContainer, object);
String fakeETag = "0x8CEB669D794AFE2";
URI copySource = view.getSigner().signGetBlob(privateContainer, "from").getEndpoint();
// failure case
try {
getApi().copyBlob(copySource, privateContainer, "to-if-match", CopyBlobOptions.builder().ifMatch(fakeETag).build());
failBecauseExceptionWasNotThrown(AzureStorageResponseException.class);
} catch (AzureStorageResponseException asre) {
assertThat(asre.getResponse().getStatusCode()).as("status code").isEqualTo(412);
}
// success case
getApi().copyBlob(copySource, privateContainer, "to-if-match", CopyBlobOptions.builder().ifMatch(eTag).build());
AzureBlob getBlob = getApi().getBlob(privateContainer, "to-if-match");
assertEquals(ByteStreams2.toByteArrayAndClose(getBlob.getPayload().openStream()), byteSource.read());
}
@Test(timeOut = 5 * 60 * 1000, dependsOnMethods = { "testCreateContainer" })
public void testCopyBlobIfNoneMatch() throws Exception {
ByteSource byteSource = TestUtils.randomByteSource().slice(0, 1024);
// create blob
AzureBlob object = getApi().newBlob();
object.getProperties().setName("from");
object.setPayload(byteSource.read());
String eTag = getApi().putBlob(privateContainer, object);
String fakeETag = "0x8CEB669D794AFE2";
URI copySource = view.getSigner().signGetBlob(privateContainer, "from").getEndpoint();
// failure case
try {
getApi().copyBlob(copySource, privateContainer, "to-if-none-match", CopyBlobOptions.builder().ifNoneMatch(eTag).build());
failBecauseExceptionWasNotThrown(AzureStorageResponseException.class);
} catch (AzureStorageResponseException asre) {
assertThat(asre.getResponse().getStatusCode()).as("status code").isEqualTo(412);
}
// success case
getApi().copyBlob(copySource, privateContainer, "to-if-none-match", CopyBlobOptions.builder().ifNoneMatch(fakeETag).build());
AzureBlob getBlob = getApi().getBlob(privateContainer, "to-if-none-match");
assertEquals(ByteStreams2.toByteArrayAndClose(getBlob.getPayload().openStream()), byteSource.read());
}
}

View File

@ -22,6 +22,8 @@ import static org.jclouds.reflect.Reflection2.method;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.net.URI;
import java.util.Date;
import java.util.Map;
import org.jclouds.Fallbacks.TrueOnNotFoundOr404;
@ -33,6 +35,7 @@ import org.jclouds.azureblob.domain.PublicAccess;
import org.jclouds.azureblob.functions.ParseBlobFromHeadersAndHttpContent;
import org.jclouds.azureblob.functions.ParseContainerPropertiesFromHeaders;
import org.jclouds.azureblob.functions.ParsePublicAccessHeader;
import org.jclouds.azureblob.options.CopyBlobOptions;
import org.jclouds.azureblob.options.CreateContainerOptions;
import org.jclouds.azureblob.options.ListBlobsOptions;
import org.jclouds.azureblob.xml.AccountNameEnumerationResultsHandler;
@ -304,6 +307,102 @@ public class AzureBlobClientTest extends BaseRestAnnotationProcessingTest<AzureB
assertFallbackClassEquals(method, null);
}
public void testCopyBlob() throws Exception {
Invokable<?, ?> method = method(AzureBlobClient.class, "copyBlob", URI.class, String.class, String.class, CopyBlobOptions.class);
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of(
URI.create("https://identity.blob.core.windows.net/fromcontainer/fromblob"), "tocontainer", "toblob", CopyBlobOptions.NONE));
assertRequestLineEquals(request,
"PUT https://identity.blob.core.windows.net/tocontainer/toblob HTTP/1.1");
checkFilters(request);
assertNonPayloadHeadersEqual(request,
"x-ms-copy-source: https://identity.blob.core.windows.net/fromcontainer/fromblob\n" +
"x-ms-version: 2013-08-15\n");
assertPayloadEquals(request, null, null, false);
}
public void testCopyBlobOverwriteUserMetadata() throws Exception {
CopyBlobOptions options = CopyBlobOptions.builder().overrideUserMetadata(ImmutableMap.of("foo", "bar")).build();
Invokable<?, ?> method = method(AzureBlobClient.class, "copyBlob", URI.class, String.class, String.class, CopyBlobOptions.class);
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of(
URI.create("https://identity.blob.core.windows.net/fromcontainer/fromblob"), "tocontainer", "toblob", options));
assertRequestLineEquals(request,
"PUT https://identity.blob.core.windows.net/tocontainer/toblob HTTP/1.1");
checkFilters(request);
assertNonPayloadHeadersEqual(request,
"x-ms-copy-source: https://identity.blob.core.windows.net/fromcontainer/fromblob\n" +
"x-ms-meta-foo: bar\n" +
"x-ms-version: 2013-08-15\n");
assertPayloadEquals(request, null, null, false);
}
public void testCopyBlobIfModifiedSince() throws Exception {
CopyBlobOptions options = CopyBlobOptions.builder().ifModifiedSince(new Date(1000)).build();
Invokable<?, ?> method = method(AzureBlobClient.class, "copyBlob", URI.class, String.class, String.class, CopyBlobOptions.class);
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of(
URI.create("https://identity.blob.core.windows.net/fromcontainer/fromblob"), "tocontainer", "toblob", options));
assertRequestLineEquals(request,
"PUT https://identity.blob.core.windows.net/tocontainer/toblob HTTP/1.1");
checkFilters(request);
assertNonPayloadHeadersEqual(request,
"x-ms-copy-source: https://identity.blob.core.windows.net/fromcontainer/fromblob\n" +
"x-ms-source-if-modified-since: Thu, 01 Jan 1970 00:00:01 GMT\n" +
"x-ms-version: 2013-08-15\n");
assertPayloadEquals(request, null, null, false);
}
public void testCopyBlobIfUnmodifiedSince() throws Exception {
CopyBlobOptions options = CopyBlobOptions.builder().ifUnmodifiedSince(new Date(1000)).build();
Invokable<?, ?> method = method(AzureBlobClient.class, "copyBlob", URI.class, String.class, String.class, CopyBlobOptions.class);
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of(
URI.create("https://identity.blob.core.windows.net/fromcontainer/fromblob"), "tocontainer", "toblob", options));
assertRequestLineEquals(request,
"PUT https://identity.blob.core.windows.net/tocontainer/toblob HTTP/1.1");
checkFilters(request);
assertNonPayloadHeadersEqual(request,
"x-ms-copy-source: https://identity.blob.core.windows.net/fromcontainer/fromblob\n" +
"x-ms-source-if-unmodified-since: Thu, 01 Jan 1970 00:00:01 GMT\n" +
"x-ms-version: 2013-08-15\n");
assertPayloadEquals(request, null, null, false);
}
public void testCopyBlobIfMatch() throws Exception {
String eTag = "0x8CEB669D794AFE2";
CopyBlobOptions options = CopyBlobOptions.builder().ifMatch(eTag).build();
Invokable<?, ?> method = method(AzureBlobClient.class, "copyBlob", URI.class, String.class, String.class, CopyBlobOptions.class);
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of(
URI.create("https://identity.blob.core.windows.net/fromcontainer/fromblob"), "tocontainer", "toblob", options));
assertRequestLineEquals(request,
"PUT https://identity.blob.core.windows.net/tocontainer/toblob HTTP/1.1");
checkFilters(request);
assertNonPayloadHeadersEqual(request,
"x-ms-copy-source: https://identity.blob.core.windows.net/fromcontainer/fromblob\n" +
"x-ms-source-if-match: " + eTag + "\n" +
"x-ms-version: 2013-08-15\n");
assertPayloadEquals(request, null, null, false);
}
public void testCopyBlobIfNoneMatch() throws Exception {
String eTag = "0x8CEB669D794AFE2";
CopyBlobOptions options = CopyBlobOptions.builder().ifNoneMatch(eTag).build();
Invokable<?, ?> method = method(AzureBlobClient.class, "copyBlob", URI.class, String.class, String.class, CopyBlobOptions.class);
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of(
URI.create("https://identity.blob.core.windows.net/fromcontainer/fromblob"), "tocontainer", "toblob", options));
assertRequestLineEquals(request,
"PUT https://identity.blob.core.windows.net/tocontainer/toblob HTTP/1.1");
checkFilters(request);
assertNonPayloadHeadersEqual(request,
"x-ms-copy-source: https://identity.blob.core.windows.net/fromcontainer/fromblob\n" +
"x-ms-source-if-none-match: " + eTag + "\n" +
"x-ms-version: 2013-08-15\n");
assertPayloadEquals(request, null, null, false);
}
@Override
protected void checkFilters(HttpRequest request) {
assertEquals(request.getFilters().size(), 1);