create(BlobHTTPHeaders headers, Metadata metadata,
- BlobAccessConditions accessConditions) {
- metadata = metadata == null ? new Metadata() : metadata;
- accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions;
-
- return postProcessResponse(this.azureBlobStorage.appendBlobs().createWithRestResponseAsync(null,
- null, 0, null, metadata, null, null,
- null, null, headers, accessConditions.leaseAccessConditions(),
- accessConditions.modifiedAccessConditions(), Context.NONE));
- }
-
- /**
- * Commits a new block of data to the end of the existing append blob. For more information, see the
- * Azure Docs.
- *
- * Note that the data passed must be replayable if retries are enabled (the default). In other words, the
- * {@code Flux} must produce the same data each time it is subscribed to.
- *
- * @param data The data to write to the blob. Note that this {@code Flux} must be replayable if retries are enabled
- * (the default). In other words, the Flowable must produce the same data each time it is subscribed to.
- * @param length The exact length of the data. It is important that this value match precisely the length of the data
- * emitted by the {@code Flux}.
- * @return Emits the successful response.
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=append_blob "Sample code for AppendBlobAsyncRawClient.appendBlock")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono appendBlock(Flux data, long length) {
- return this.appendBlock(data, length, null);
- }
-
- /**
- * Commits a new block of data to the end of the existing append blob. For more information, see the
- * Azure Docs.
- *
- * Note that the data passed must be replayable if retries are enabled (the default). In other words, the
- * {@code Flux} must produce the same data each time it is subscribed to.
- *
- * @param data The data to write to the blob. Note that this {@code Flux} must be replayable if retries are enabled
- * (the default). In other words, the Flowable must produce the same data each time it is subscribed to.
- * @param length The exact length of the data. It is important that this value match precisely the length of the data
- * emitted by the {@code Flux}.
- * @param appendBlobAccessConditions {@link AppendBlobAccessConditions}
- * @return Emits the successful response.
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=append_blob "Sample code for AppendBlobAsyncRawClient.appendBlock")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono appendBlock(Flux data, long length,
- AppendBlobAccessConditions appendBlobAccessConditions) {
- appendBlobAccessConditions = appendBlobAccessConditions == null ? new AppendBlobAccessConditions()
- : appendBlobAccessConditions;
-
- return postProcessResponse(this.azureBlobStorage.appendBlobs().appendBlockWithRestResponseAsync(
- null, null, data, length, null, null,
- null, null, null, null,
- appendBlobAccessConditions.leaseAccessConditions(),
- appendBlobAccessConditions.appendPositionAccessConditions(),
- appendBlobAccessConditions.modifiedAccessConditions(), Context.NONE));
- }
-
- /**
- * Commits a new block of data from another blob to the end of this append blob. For more information, see the
- * Azure Docs.
- *
- *
- * @param sourceURL The url to the blob that will be the source of the copy. A source blob in the same storage account can
- * be authenticated via Shared Key. However, if the source is a blob in another account, the source blob
- * must either be public or must be authenticated via a shared access signature. If the source blob is
- * public, no authentication is required to perform the operation.
- * @param sourceRange The source {@link BlobRange} to copy.
- * @return Emits the successful response.
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=append_from_url "Sample code for AppendBlobAsyncRawClient.appendBlockFromUrl")]
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono appendBlockFromUrl(URL sourceURL, BlobRange sourceRange) {
- return this.appendBlockFromUrl(sourceURL, sourceRange, null, null,
- null);
- }
-
- /**
- * Commits a new block of data from another blob to the end of this append blob. For more information, see the
- * Azure Docs.
- *
- *
- * @param sourceURL The url to the blob that will be the source of the copy. A source blob in the same storage account can
- * be authenticated via Shared Key. However, if the source is a blob in another account, the source blob
- * must either be public or must be authenticated via a shared access signature. If the source blob is
- * public, no authentication is required to perform the operation.
- * @param sourceRange {@link BlobRange}
- * @param sourceContentMD5 An MD5 hash of the block content from the source blob. If specified, the service will calculate the MD5
- * of the received data and fail the request if it does not match the provided MD5.
- * @param destAccessConditions {@link AppendBlobAccessConditions}
- * @param sourceAccessConditions {@link SourceModifiedAccessConditions}
- * @return Emits the successful response.
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=append_from_url "Sample code for AppendBlobAsyncRawClient.appendBlockFromUrl")]
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono appendBlockFromUrl(URL sourceURL, BlobRange sourceRange,
- byte[] sourceContentMD5, AppendBlobAccessConditions destAccessConditions,
- SourceModifiedAccessConditions sourceAccessConditions) {
-
- sourceRange = sourceRange == null ? new BlobRange(0) : sourceRange;
- destAccessConditions = destAccessConditions == null
- ? new AppendBlobAccessConditions() : destAccessConditions;
-
- return postProcessResponse(
- this.azureBlobStorage.appendBlobs().appendBlockFromUrlWithRestResponseAsync(null, null,
- sourceURL, 0, sourceRange.toString(), sourceContentMD5, null, null,
- destAccessConditions.leaseAccessConditions(),
- destAccessConditions.appendPositionAccessConditions(),
- destAccessConditions.modifiedAccessConditions(), sourceAccessConditions, Context.NONE));
- }
-}
diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/AppendBlobClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/AppendBlobClient.java
index 47a379649659f..246fe645af179 100644
--- a/storage/client/blob/src/main/java/com/azure/storage/blob/AppendBlobClient.java
+++ b/storage/client/blob/src/main/java/com/azure/storage/blob/AppendBlobClient.java
@@ -11,18 +11,19 @@
import com.azure.storage.blob.models.BlobRange;
import com.azure.storage.blob.models.Metadata;
import com.azure.storage.blob.models.SourceModifiedAccessConditions;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufAllocator;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;
import java.io.InputStream;
import java.net.URL;
-import java.nio.ByteBuffer;
import java.time.Duration;
/**
- * Client to an append blob. It may only be instantiated through a {@link AppendBlobClientBuilder}, via
+ * Client to an append blob. It may only be instantiated through a {@link BlobClientBuilder}, via
* the method {@link BlobClient#asAppendBlobClient()}, or via the method
* {@link ContainerClient#getAppendBlobClient(String)}. This class does not hold
* any state about a particular blob, but is instead a convenient way of sending appropriate
@@ -37,28 +38,27 @@
* for more information.
*/
public final class AppendBlobClient extends BlobClient {
-
- AppendBlobAsyncClient appendBlobAsyncClient;
+ private AppendBlobAsyncClient appendBlobAsyncClient;
/**
* Indicates the maximum number of bytes that can be sent in a call to appendBlock.
*/
- public static final int MAX_APPEND_BLOCK_BYTES = 4 * Constants.MB;
+ public static final int MAX_APPEND_BLOCK_BYTES = AppendBlobAsyncClient.MAX_APPEND_BLOCK_BYTES;
/**
* Indicates the maximum number of blocks allowed in an append blob.
*/
- public static final int MAX_BLOCKS = 50000;
+ public static final int MAX_BLOCKS = AppendBlobAsyncClient.MAX_BLOCKS;
/**
- * Package-private constructor for use by {@link AppendBlobClientBuilder}.
+ * Package-private constructor for use by {@link BlobClientBuilder}.
* @param appendBlobAsyncClient the async append blob client
*/
AppendBlobClient(AppendBlobAsyncClient appendBlobAsyncClient) {
super(appendBlobAsyncClient);
this.appendBlobAsyncClient = appendBlobAsyncClient;
}
-
+
/**
* Creates and opens an output stream to write data to the append blob. If the blob already exists on the service,
* it will be overwritten.
@@ -160,7 +160,7 @@ public Response appendBlock(InputStream data, long length) {
*/
public Response appendBlock(InputStream data, long length,
AppendBlobAccessConditions appendBlobAccessConditions, Duration timeout) {
- Flux fbb = Flux.range(0, (int) Math.ceil((double) length / (double) MAX_APPEND_BLOCK_BYTES))
+ Flux fbb = Flux.range(0, (int) Math.ceil((double) length / (double) MAX_APPEND_BLOCK_BYTES))
.map(i -> i * MAX_APPEND_BLOCK_BYTES)
.concatMap(pos -> Mono.fromCallable(() -> {
long count = pos + MAX_APPEND_BLOCK_BYTES > length ? length - pos : MAX_APPEND_BLOCK_BYTES;
@@ -169,7 +169,8 @@ public Response appendBlock(InputStream data, long length,
while (read < count) {
read += data.read(cache, read, (int) count - read);
}
- return ByteBuffer.wrap(cache);
+
+ return ByteBufAllocator.DEFAULT.buffer((int) count).writeBytes(cache);
}));
Mono> response = appendBlobAsyncClient.appendBlock(fbb.subscribeOn(Schedulers.elastic()), length, appendBlobAccessConditions);
diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/AppendBlobClientBuilder.java b/storage/client/blob/src/main/java/com/azure/storage/blob/AppendBlobClientBuilder.java
deleted file mode 100644
index c46883e7fecf9..0000000000000
--- a/storage/client/blob/src/main/java/com/azure/storage/blob/AppendBlobClientBuilder.java
+++ /dev/null
@@ -1,333 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package com.azure.storage.blob;
-
-import com.azure.core.credentials.TokenCredential;
-import com.azure.core.http.HttpClient;
-import com.azure.core.http.HttpPipeline;
-import com.azure.core.http.policy.AddDatePolicy;
-import com.azure.core.http.policy.BearerTokenAuthenticationPolicy;
-import com.azure.core.http.policy.HttpLogDetailLevel;
-import com.azure.core.http.policy.HttpLoggingPolicy;
-import com.azure.core.http.policy.HttpPipelinePolicy;
-import com.azure.core.http.policy.RequestIdPolicy;
-import com.azure.core.http.policy.UserAgentPolicy;
-import com.azure.core.implementation.util.ImplUtils;
-import com.azure.core.util.configuration.Configuration;
-import com.azure.core.util.configuration.ConfigurationManager;
-import com.azure.storage.blob.implementation.AzureBlobStorageBuilder;
-import com.azure.storage.common.credentials.SASTokenCredential;
-import com.azure.storage.common.credentials.SharedKeyCredential;
-import com.azure.storage.common.policy.RequestRetryOptions;
-import com.azure.storage.common.policy.RequestRetryPolicy;
-import com.azure.storage.common.policy.SASTokenCredentialPolicy;
-import com.azure.storage.common.policy.SharedKeyCredentialPolicy;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Objects;
-
-/**
- * Fluent AppendBlobClientBuilder for instantiating a {@link AppendBlobClient} or {@link AppendBlobAsyncClient}
- * using {@link AppendBlobClientBuilder#buildAsyncClient()} or {@link AppendBlobClientBuilder#buildAsyncClient()} respectively.
- *
- *
- * The following information must be provided on this builder:
- *
- *
- * - the endpoint through {@code .endpoint()}, including the container name and blob name, in the format of {@code https://{accountName}.blob.core.windows.net/{containerName}/{blobName}}.
- *
- the credential through {@code .credential()} or {@code .connectionString()} if the container is not publicly accessible.
- *
- *
- *
- * Once all the configurations are set on this builder, call {@code .buildClient()} to create a
- * {@link AppendBlobClient} or {@code .buildAsyncClient()} to create a {@link AppendBlobAsyncClient}.
- */
-public final class AppendBlobClientBuilder {
- private static final String ACCOUNT_NAME = "accountname";
- private static final String ACCOUNT_KEY = "accountkey";
- private static final String ENDPOINT_PROTOCOL = "defaultendpointsprotocol";
- private static final String ENDPOINT_SUFFIX = "endpointsuffix";
-
- private final List policies;
-
- private String endpoint;
- private String containerName;
- private String blobName;
- private String snapshot;
- private SharedKeyCredential sharedKeyCredential;
- private TokenCredential tokenCredential;
- private SASTokenCredential sasTokenCredential;
- private HttpClient httpClient;
- private HttpLogDetailLevel logLevel;
- private RequestRetryOptions retryOptions;
- private Configuration configuration;
-
- /**
- * Creates a builder instance that is able to configure and construct {@link AppendBlobClient AppendBlobClients}
- * and {@link AppendBlobAsyncClient AppendBlobAsyncClients}.
- */
- public AppendBlobClientBuilder() {
- retryOptions = new RequestRetryOptions();
- logLevel = HttpLogDetailLevel.NONE;
- policies = new ArrayList<>();
- }
-
- private AzureBlobStorageBuilder buildImpl() {
- Objects.requireNonNull(endpoint);
- Objects.requireNonNull(containerName);
- Objects.requireNonNull(blobName);
-
- // Closest to API goes first, closest to wire goes last.
- final List policies = new ArrayList<>();
-
- if (configuration == null) {
- configuration = ConfigurationManager.getConfiguration();
- }
- policies.add(new UserAgentPolicy(BlobConfiguration.NAME, BlobConfiguration.VERSION, configuration));
- policies.add(new RequestIdPolicy());
- policies.add(new AddDatePolicy());
-
- if (sharedKeyCredential != null) {
- policies.add(new SharedKeyCredentialPolicy(sharedKeyCredential));
- } else if (tokenCredential != null) {
- policies.add(new BearerTokenAuthenticationPolicy(tokenCredential, String.format("%s/.default", endpoint)));
- } else if (sasTokenCredential != null) {
- policies.add(new SASTokenCredentialPolicy(sasTokenCredential));
- } else {
- policies.add(new AnonymousCredentialPolicy());
- }
-
- policies.add(new RequestRetryPolicy(retryOptions));
-
- policies.addAll(this.policies);
- policies.add(new HttpLoggingPolicy(logLevel));
-
- HttpPipeline pipeline = HttpPipeline.builder()
- .policies(policies.toArray(new HttpPipelinePolicy[0]))
- .httpClient(httpClient)
- .build();
-
- return new AzureBlobStorageBuilder()
- .url(String.format("%s/%s/%s", endpoint, containerName, blobName))
- .pipeline(pipeline);
- }
-
- /**
- * @return a {@link AppendBlobClient} created from the configurations in this builder.
- */
- public AppendBlobClient buildClient() {
- return new AppendBlobClient(buildAsyncClient());
- }
-
- /**
- * @return a {@link AppendBlobAsyncClient} created from the configurations in this builder.
- */
- public AppendBlobAsyncClient buildAsyncClient() {
- return new AppendBlobAsyncClient(buildImpl(), snapshot);
- }
-
- /**
- * Sets the service endpoint, additionally parses it for information (SAS token, container name, blob name)
- * @param endpoint URL of the service
- * @return the updated AppendBlobClientBuilder object
- * @throws IllegalArgumentException If {@code endpoint} is a malformed URL or is using an unknown host.
- */
- public AppendBlobClientBuilder endpoint(String endpoint) {
- Objects.requireNonNull(endpoint);
- URL url;
- try {
- url = new URL(endpoint);
- BlobURLParts parts = URLParser.parse(url);
- this.endpoint = parts.scheme() + "://" + parts.host();
-
- if (parts.containerName() != null) {
- this.containerName = parts.containerName();
- }
-
- if (parts.blobName() != null) {
- this.blobName = parts.blobName();
- }
-
- if (parts.snapshot() != null) {
- this.snapshot = parts.snapshot();
- }
- } catch (MalformedURLException ex) {
- throw new IllegalArgumentException("The Azure Storage Blob endpoint url is malformed.");
- }
-
- SASTokenCredential credential = SASTokenCredential.fromQuery(url.getQuery());
- if (credential != null) {
- this.credential(credential);
- }
-
- return this;
- }
-
- /**
- * Sets the name of the container this client is connecting to.
- * @param containerName the name of the container
- * @return the updated AppendBlobClientBuilder object
- */
- public AppendBlobClientBuilder containerName(String containerName) {
- this.containerName = containerName;
- return this;
- }
-
- /**
- * Sets the name of the blob this client is connecting to.
- * @param blobName the name of the blob
- * @return the updated AppendBlobClientBuilder object
- */
- public AppendBlobClientBuilder blobName(String blobName) {
- this.blobName = blobName;
- return this;
- }
-
- /**
- * Sets the snapshot of the blob this client is connecting to.
- * @param snapshot the snapshot identifier for the blob
- * @return the updated AppendBlobClientBuilder object
- */
- public AppendBlobClientBuilder snapshot(String snapshot) {
- this.snapshot = snapshot;
- return this;
- }
-
- /**
- * Sets the credential used to authorize requests sent to the service
- * @param credential authorization credential
- * @return the updated AppendBlobClientBuilder object
- */
- public AppendBlobClientBuilder credential(SharedKeyCredential credential) {
- this.sharedKeyCredential = credential;
- this.tokenCredential = null;
- this.sasTokenCredential = null;
- return this;
- }
-
- /**
- * Sets the credential used to authorize requests sent to the service
- * @param credential authorization credential
- * @return the updated AppendBlobClientBuilder object
- */
- public AppendBlobClientBuilder credential(TokenCredential credential) {
- this.tokenCredential = credential;
- this.sharedKeyCredential = null;
- this.sasTokenCredential = null;
- return this;
- }
-
- /**
- * Sets the credential used to authorize requests sent to the service
- * @param credential authorization credential
- * @return the updated AppendBlobClientBuilder object
- */
- public AppendBlobClientBuilder credential(SASTokenCredential credential) {
- this.sasTokenCredential = credential;
- this.sharedKeyCredential = null;
- this.tokenCredential = null;
- return this;
- }
-
- /**
- * Clears the credential used to authorize requests sent to the service
- * @return the updated AppendBlobClientBuilder object
- */
- public AppendBlobClientBuilder anonymousCredential() {
- this.sharedKeyCredential = null;
- this.tokenCredential = null;
- this.sasTokenCredential = null;
- return this;
- }
-
- /**
- * Sets the connection string for the service, parses it for authentication information (account name, account key)
- * @param connectionString connection string from access keys section
- * @return the updated AppendBlobClientBuilder object
- * @throws IllegalArgumentException If {@code connectionString} doesn't contain AccountName or AccountKey.
- */
- public AppendBlobClientBuilder connectionString(String connectionString) {
- Objects.requireNonNull(connectionString);
-
- Map connectionKVPs = new HashMap<>();
- for (String s : connectionString.split(";")) {
- String[] kvp = s.split("=", 2);
- connectionKVPs.put(kvp[0].toLowerCase(Locale.ROOT), kvp[1]);
- }
-
- String accountName = connectionKVPs.get(ACCOUNT_NAME);
- String accountKey = connectionKVPs.get(ACCOUNT_KEY);
- String endpointProtocol = connectionKVPs.get(ENDPOINT_PROTOCOL);
- String endpointSuffix = connectionKVPs.get(ENDPOINT_SUFFIX);
-
- if (ImplUtils.isNullOrEmpty(accountName) || ImplUtils.isNullOrEmpty(accountKey)) {
- throw new IllegalArgumentException("Connection string must contain 'AccountName' and 'AccountKey'.");
- }
-
- if (!ImplUtils.isNullOrEmpty(endpointProtocol) && !ImplUtils.isNullOrEmpty(endpointSuffix)) {
- String endpoint = String.format("%s://%s.blob.%s", endpointProtocol, accountName, endpointSuffix.replaceFirst("^\\.", ""));
- endpoint(endpoint);
- }
-
- // Use accountName and accountKey to get the SAS token using the credential class.
- return credential(new SharedKeyCredential(accountName, accountKey));
- }
-
- /**
- * Sets the http client used to send service requests
- * @param httpClient http client to send requests
- * @return the updated AppendBlobClientBuilder object
- */
- public AppendBlobClientBuilder httpClient(HttpClient httpClient) {
- this.httpClient = httpClient;
- return this;
- }
-
- /**
- * Adds a pipeline policy to apply on each request sent
- * @param pipelinePolicy a pipeline policy
- * @return the updated AppendBlobClientBuilder object
- */
- public AppendBlobClientBuilder addPolicy(HttpPipelinePolicy pipelinePolicy) {
- this.policies.add(pipelinePolicy);
- return this;
- }
-
- /**
- * Sets the logging level for service requests
- * @param logLevel logging level
- * @return the updated AppendBlobClientBuilder object
- */
- public AppendBlobClientBuilder httpLogDetailLevel(HttpLogDetailLevel logLevel) {
- this.logLevel = logLevel;
- return this;
- }
-
- /**
- * Sets the configuration object used to retrieve environment configuration values used to buildClient the client with
- * when they are not set in the appendBlobClientBuilder, defaults to Configuration.NONE
- * @param configuration configuration store
- * @return the updated AppendBlobClientBuilder object
- */
- public AppendBlobClientBuilder configuration(Configuration configuration) {
- this.configuration = configuration;
- return this;
- }
-
- /**
- * Sets the request retry options for all the requests made through the client.
- * @param retryOptions the options to configure retry behaviors
- * @return the updated AppendBlobClientBuilder object
- */
- public AppendBlobClientBuilder retryOptions(RequestRetryOptions retryOptions) {
- this.retryOptions = retryOptions;
- return this;
- }
-}
diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobAsyncClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobAsyncClient.java
index 7ec72ecf30b53..c8ceb3f311d3f 100644
--- a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobAsyncClient.java
+++ b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobAsyncClient.java
@@ -9,7 +9,9 @@
import com.azure.core.http.rest.VoidResponse;
import com.azure.core.implementation.http.UrlBuilder;
import com.azure.core.implementation.util.FluxUtil;
+import com.azure.core.util.Context;
import com.azure.storage.blob.implementation.AzureBlobStorageBuilder;
+import com.azure.storage.blob.implementation.AzureBlobStorageImpl;
import com.azure.storage.blob.models.AccessTier;
import com.azure.storage.blob.models.BlobAccessConditions;
import com.azure.storage.blob.models.BlobHTTPHeaders;
@@ -20,7 +22,10 @@
import com.azure.storage.blob.models.Metadata;
import com.azure.storage.blob.models.ModifiedAccessConditions;
import com.azure.storage.blob.models.ReliableDownloadOptions;
+import com.azure.storage.blob.models.SourceModifiedAccessConditions;
import com.azure.storage.blob.models.StorageAccountInfo;
+import com.azure.storage.blob.models.UserDelegationKey;
+import com.azure.storage.common.credentials.SharedKeyCredential;
import io.netty.buffer.ByteBuf;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -35,85 +40,94 @@
import java.nio.channels.AsynchronousFileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
+import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.List;
+import static com.azure.storage.blob.Utility.postProcessResponse;
+
/**
- * Client to a blob of any type: block, append, or page. It may only be instantiated through a {@link BlobClientBuilder} or via
- * the method {@link ContainerAsyncClient#getBlobAsyncClient(String)}. This class does not hold any state about a particular
- * blob, but is instead a convenient way of sending appropriate requests to the resource on the service.
+ * Client to a blob of any type: block, append, or page. It may only be instantiated through a {@link BlobClientBuilder}
+ * or via the method {@link ContainerAsyncClient#getBlobAsyncClient(String)}. This class does not hold any state about a
+ * particular blob, but is instead a convenient way of sending appropriate requests to the resource on the service.
*
*
* This client offers the ability to download blobs. Note that uploading data is specific to each type of blob. Please
* refer to the {@link BlockBlobClient}, {@link PageBlobClient}, or {@link AppendBlobClient} for upload options. This
- * client can be converted into one of these clients easily through the methods {@link #asBlockBlobAsyncClient},
- * {@link #asPageBlobAsyncClient}, and {@link #asAppendBlobAsyncClient()}.
+ * client can be converted into one of these clients easily through the methods {@link #asBlockBlobAsyncClient}, {@link
+ * #asPageBlobAsyncClient}, and {@link #asAppendBlobAsyncClient()}.
*
*
* This client contains operations on a blob. Operations on a container are available on {@link ContainerAsyncClient},
* and operations on the service are available on {@link StorageAsyncClient}.
*
*
- * Please refer to the Azure Docs
- * for more information.
+ * Please refer to the Azure
+ * Docs for more information.
*
*
- * Note this client is an async client that returns reactive responses from Spring Reactor Core
- * project (https://projectreactor.io/). Calling the methods in this client will NOT
- * start the actual network operation, until {@code .subscribe()} is called on the reactive response.
- * You can simply convert one of these responses to a {@link java.util.concurrent.CompletableFuture}
- * object through {@link Mono#toFuture()}.
+ * Note this client is an async client that returns reactive responses from Spring Reactor Core project
+ * (https://projectreactor.io/). Calling the methods in this client will NOT start the actual network
+ * operation, until {@code .subscribe()} is called on the reactive response. You can simply convert one of these
+ * responses to a {@link java.util.concurrent.CompletableFuture} object through {@link Mono#toFuture()}.
*/
+@SuppressWarnings({"unused", "WeakerAccess"})
public class BlobAsyncClient {
private static final int BLOB_DEFAULT_DOWNLOAD_BLOCK_SIZE = 4 * Constants.MB;
private static final int BLOB_MAX_DOWNLOAD_BLOCK_SIZE = 100 * Constants.MB;
- final BlobAsyncRawClient blobAsyncRawClient;
+ final AzureBlobStorageImpl azureBlobStorage;
+ protected final String snapshot;
/**
* Package-private constructor for use by {@link BlobClientBuilder}.
+ *
* @param azureBlobStorageBuilder the API client builder for blob storage API
*/
BlobAsyncClient(AzureBlobStorageBuilder azureBlobStorageBuilder, String snapshot) {
- this.blobAsyncRawClient = new BlobAsyncRawClient(azureBlobStorageBuilder.build(), snapshot);
+ this.azureBlobStorage = azureBlobStorageBuilder.build();
+ this.snapshot = snapshot;
}
/**
* Creates a new {@link BlockBlobAsyncClient} to this resource, maintaining configurations. Only do this for blobs
* that are known to be block blobs.
*
- * @return
- * A {@link BlockBlobAsyncClient} to this resource.
+ * @return A {@link BlockBlobAsyncClient} to this resource.
*/
public BlockBlobAsyncClient asBlockBlobAsyncClient() {
- return new BlockBlobAsyncClient(new AzureBlobStorageBuilder().url(getBlobUrl().toString()).pipeline(blobAsyncRawClient.azureBlobStorage.httpPipeline()), blobAsyncRawClient.snapshot);
+ return new BlockBlobAsyncClient(new AzureBlobStorageBuilder()
+ .url(getBlobUrl().toString())
+ .pipeline(azureBlobStorage.httpPipeline()), snapshot);
}
/**
* Creates a new {@link AppendBlobAsyncClient} to this resource, maintaining configurations. Only do this for blobs
* that are known to be append blobs.
*
- * @return
- * A {@link AppendBlobAsyncClient} to this resource.
+ * @return A {@link AppendBlobAsyncClient} to this resource.
*/
public AppendBlobAsyncClient asAppendBlobAsyncClient() {
- return new AppendBlobAsyncClient(new AzureBlobStorageBuilder().url(getBlobUrl().toString()).pipeline(blobAsyncRawClient.azureBlobStorage.httpPipeline()), blobAsyncRawClient.snapshot);
+ return new AppendBlobAsyncClient(new AzureBlobStorageBuilder()
+ .url(getBlobUrl().toString())
+ .pipeline(azureBlobStorage.httpPipeline()), snapshot);
}
/**
* Creates a new {@link PageBlobAsyncClient} to this resource, maintaining configurations. Only do this for blobs
* that are known to be page blobs.
*
- * @return
- * A {@link PageBlobAsyncClient} to this resource.
+ * @return A {@link PageBlobAsyncClient} to this resource.
*/
public PageBlobAsyncClient asPageBlobAsyncClient() {
- return new PageBlobAsyncClient(new AzureBlobStorageBuilder().url(getBlobUrl().toString()).pipeline(blobAsyncRawClient.azureBlobStorage.httpPipeline()), blobAsyncRawClient.snapshot);
+ return new PageBlobAsyncClient(new AzureBlobStorageBuilder()
+ .url(getBlobUrl().toString())
+ .pipeline(azureBlobStorage.httpPipeline()), snapshot);
}
/**
- * Initializes a {@link ContainerAsyncClient} object pointing to the container this blob is in. This method does
- * not create a container. It simply constructs the URL to the container and offers access to methods relevant to
+ * Initializes a {@link ContainerAsyncClient} object pointing to the container this blob is in. This method does not
+ * create a container. It simply constructs the URL to the container and offers access to methods relevant to
* containers.
*
* @return A {@link ContainerAsyncClient} object pointing to the container containing the blob
@@ -122,31 +136,31 @@ public ContainerAsyncClient getContainerAsyncClient() {
BlobURLParts parts = URLParser.parse(getBlobUrl());
return new ContainerAsyncClient(new AzureBlobStorageBuilder()
.url(String.format("%s://%s/%s", parts.scheme(), parts.host(), parts.containerName()))
- .pipeline(blobAsyncRawClient.azureBlobStorage.httpPipeline()));
+ .pipeline(azureBlobStorage.httpPipeline()));
}
/**
* Gets the URL of the blob represented by this client.
+ *
* @return the URL.
* @throws RuntimeException If the blob is using a malformed URL.
*/
public URL getBlobUrl() {
try {
- UrlBuilder urlBuilder = UrlBuilder.parse(blobAsyncRawClient.azureBlobStorage.url());
- if (blobAsyncRawClient.snapshot != null) {
- urlBuilder.query("snapshot=" + blobAsyncRawClient.snapshot);
+ UrlBuilder urlBuilder = UrlBuilder.parse(azureBlobStorage.url());
+ if (snapshot != null) {
+ urlBuilder.query("snapshot=" + snapshot);
}
return urlBuilder.toURL();
} catch (MalformedURLException e) {
- throw new RuntimeException(String.format("Invalid URL on %s: %s" + getClass().getSimpleName(), blobAsyncRawClient.azureBlobStorage.url()), e);
+ throw new RuntimeException(String.format("Invalid URL on %s: %s" + getClass().getSimpleName(), azureBlobStorage.url()), e);
}
}
/**
* Gets if the blob this client represents exists in the cloud.
*
- * @return
- * true if the blob exists, false if it doesn't
+ * @return true if the blob exists, false if it doesn't
*/
public Mono> exists() {
return this.getProperties()
@@ -161,11 +175,8 @@ public Mono> exists() {
* Copies the data at the source URL to a blob. For more information, see the
* Azure Docs
*
- * @param sourceURL
- * The source URL to copy from. URLs outside of Azure may only be copied to block blobs.
- *
- * @return
- * A reactive response containing the copy ID for the long running operation.
+ * @param sourceURL The source URL to copy from. URLs outside of Azure may only be copied to block blobs.
+ * @return A reactive response containing the copy ID for the long running operation.
*/
public Mono> startCopyFromURL(URL sourceURL) {
return this.startCopyFromURL(sourceURL, null, null, null);
@@ -175,37 +186,40 @@ public Mono> startCopyFromURL(URL sourceURL) {
* Copies the data at the source URL to a blob. For more information, see the
* Azure Docs
*
- * @param sourceURL
- * The source URL to copy from. URLs outside of Azure may only be copied to block blobs.
- * @param metadata
- * {@link Metadata}
- * @param sourceModifiedAccessConditions
- * {@link ModifiedAccessConditions} against the source. Standard HTTP Access conditions related to the
- * modification of data. ETag and LastModifiedTime are used to construct conditions related to when the blob
- * was changed relative to the given request. The request will fail if the specified condition is not
- * satisfied.
- * @param destAccessConditions
- * {@link BlobAccessConditions} against the destination.
- *
- * @return
- * A reactive response containing the copy ID for the long running operation.
- */
- public Mono> startCopyFromURL(URL sourceURL, Metadata metadata,
- ModifiedAccessConditions sourceModifiedAccessConditions, BlobAccessConditions destAccessConditions) {
- return blobAsyncRawClient
- .startCopyFromURL(sourceURL, metadata, sourceModifiedAccessConditions, destAccessConditions)
+ * @param sourceURL The source URL to copy from. URLs outside of Azure may only be copied to block blobs.
+ * @param metadata {@link Metadata}
+ * @param sourceModifiedAccessConditions {@link ModifiedAccessConditions} against the source. Standard HTTP Access
+ * conditions related to the modification of data. ETag and LastModifiedTime are used to construct conditions
+ * related to when the blob was changed relative to the given request. The request will fail if the specified
+ * condition is not satisfied.
+ * @param destAccessConditions {@link BlobAccessConditions} against the destination.
+ * @return A reactive response containing the copy ID for the long running operation.
+ */
+ public Mono> startCopyFromURL(URL sourceURL, Metadata metadata, ModifiedAccessConditions sourceModifiedAccessConditions, BlobAccessConditions destAccessConditions) {
+ metadata = metadata == null ? new Metadata() : metadata;
+ sourceModifiedAccessConditions = sourceModifiedAccessConditions == null
+ ? new ModifiedAccessConditions() : sourceModifiedAccessConditions;
+ destAccessConditions = destAccessConditions == null ? new BlobAccessConditions() : destAccessConditions;
+
+ // We want to hide the SourceAccessConditions type from the user for consistency's sake, so we convert here.
+ SourceModifiedAccessConditions sourceConditions = new SourceModifiedAccessConditions()
+ .sourceIfModifiedSince(sourceModifiedAccessConditions.ifModifiedSince())
+ .sourceIfUnmodifiedSince(sourceModifiedAccessConditions.ifUnmodifiedSince())
+ .sourceIfMatch(sourceModifiedAccessConditions.ifMatch())
+ .sourceIfNoneMatch(sourceModifiedAccessConditions.ifNoneMatch());
+
+ return postProcessResponse(this.azureBlobStorage.blobs().startCopyFromURLWithRestResponseAsync(
+ null, null, sourceURL, null, metadata, null, sourceConditions,
+ destAccessConditions.modifiedAccessConditions(), destAccessConditions.leaseAccessConditions(), Context.NONE))
.map(rb -> new SimpleResponse<>(rb, rb.deserializedHeaders().copyId()));
}
/**
* Stops a pending copy that was previously started and leaves a destination blob with 0 length and metadata.
*
- * @param copyId
- * The id of the copy operation to abort. Returned as the {@code copyId} field on the {@link
- * BlobStartCopyFromURLHeaders} object.
- *
- * @return
- * A reactive response signalling completion.
+ * @param copyId The id of the copy operation to abort. Returned as the {@code copyId} field on the {@link
+ * BlobStartCopyFromURLHeaders} object.
+ * @return A reactive response signalling completion.
*/
public Mono abortCopyFromURL(String copyId) {
return this.abortCopyFromURL(copyId, null);
@@ -214,30 +228,23 @@ public Mono abortCopyFromURL(String copyId) {
/**
* Stops a pending copy that was previously started and leaves a destination blob with 0 length and metadata.
*
- * @param copyId
- * The id of the copy operation to abort. Returned as the {@code copyId} field on the {@link
- * BlobStartCopyFromURLHeaders} object.
- * @param leaseAccessConditions
- * By setting lease access conditions, requests will fail if the provided lease does not match the active
- * lease on the blob.
- *
- * @return
- * A reactive response signalling completion.
+ * @param copyId The id of the copy operation to abort. Returned as the {@code copyId} field on the {@link
+ * BlobStartCopyFromURLHeaders} object.
+ * @param leaseAccessConditions By setting lease access conditions, requests will fail if the provided lease does
+ * not match the active lease on the blob.
+ * @return A reactive response signalling completion.
*/
public Mono abortCopyFromURL(String copyId, LeaseAccessConditions leaseAccessConditions) {
- return blobAsyncRawClient
- .abortCopyFromURL(copyId, leaseAccessConditions)
+ return postProcessResponse(this.azureBlobStorage.blobs().abortCopyFromURLWithRestResponseAsync(
+ null, null, copyId, null, null, leaseAccessConditions, Context.NONE))
.map(VoidResponse::new);
}
/**
* Copies the data at the source URL to a blob and waits for the copy to complete before returning a response.
*
- * @param copySource
- * The source URL to copy from.
- *
- * @return
- * A reactive response containing the copy ID for the long running operation.
+ * @param copySource The source URL to copy from.
+ * @return A reactive response containing the copy ID for the long running operation.
*/
public Mono> copyFromURL(URL copySource) {
return this.copyFromURL(copySource, null, null, null);
@@ -246,63 +253,108 @@ public Mono> copyFromURL(URL copySource) {
/**
* Copies the data at the source URL to a blob and waits for the copy to complete before returning a response.
*
- * @param copySource
- * The source URL to copy from. URLs outside of Azure may only be copied to block blobs.
- * @param metadata
- * {@link Metadata}
- * @param sourceModifiedAccessConditions
- * {@link ModifiedAccessConditions} against the source. Standard HTTP Access conditions related to the
- * modification of data. ETag and LastModifiedTime are used to construct conditions related to when the blob
- * was changed relative to the given request. The request will fail if the specified condition is not
- * satisfied.
- * @param destAccessConditions
- * {@link BlobAccessConditions} against the destination.
- *
- * @return
- * A reactive response containing the copy ID for the long running operation.
- */
- public Mono> copyFromURL(URL copySource, Metadata metadata,
- ModifiedAccessConditions sourceModifiedAccessConditions, BlobAccessConditions destAccessConditions) {
- return blobAsyncRawClient
- .syncCopyFromURL(copySource, metadata, sourceModifiedAccessConditions, destAccessConditions)
+ * @param copySource The source URL to copy from. URLs outside of Azure may only be copied to block blobs.
+ * @param metadata {@link Metadata}
+ * @param sourceModifiedAccessConditions {@link ModifiedAccessConditions} against the source. Standard HTTP Access
+ * conditions related to the modification of data. ETag and LastModifiedTime are used to construct conditions
+ * related to when the blob was changed relative to the given request. The request will fail if the specified
+ * condition is not satisfied.
+ * @param destAccessConditions {@link BlobAccessConditions} against the destination.
+ * @return A reactive response containing the copy ID for the long running operation.
+ */
+ public Mono> copyFromURL(URL copySource, Metadata metadata, ModifiedAccessConditions sourceModifiedAccessConditions, BlobAccessConditions destAccessConditions) {
+ metadata = metadata == null ? new Metadata() : metadata;
+ sourceModifiedAccessConditions = sourceModifiedAccessConditions == null
+ ? new ModifiedAccessConditions() : sourceModifiedAccessConditions;
+ destAccessConditions = destAccessConditions == null ? new BlobAccessConditions() : destAccessConditions;
+
+ // We want to hide the SourceAccessConditions type from the user for consistency's sake, so we convert here.
+ SourceModifiedAccessConditions sourceConditions = new SourceModifiedAccessConditions()
+ .sourceIfModifiedSince(sourceModifiedAccessConditions.ifModifiedSince())
+ .sourceIfUnmodifiedSince(sourceModifiedAccessConditions.ifUnmodifiedSince())
+ .sourceIfMatch(sourceModifiedAccessConditions.ifMatch())
+ .sourceIfNoneMatch(sourceModifiedAccessConditions.ifNoneMatch());
+
+ return postProcessResponse(this.azureBlobStorage.blobs().copyFromURLWithRestResponseAsync(
+ null, null, copySource, null, metadata, null, sourceConditions,
+ destAccessConditions.modifiedAccessConditions(), destAccessConditions.leaseAccessConditions(), Context.NONE))
.map(rb -> new SimpleResponse<>(rb, rb.deserializedHeaders().copyId()));
}
/**
- * Reads the entire blob. Uploading data must be done from the {@link BlockBlobClient}, {@link PageBlobClient}, or {@link AppendBlobClient}.
+ * Reads the entire blob. Uploading data must be done from the {@link BlockBlobClient}, {@link PageBlobClient}, or
+ * {@link AppendBlobClient}.
*
- * @return
- * A reactive response containing the blob data.
+ * @return A reactive response containing the blob data.
*/
public Mono>> download() {
return this.download(null, null, false, null);
}
/**
- * Reads a range of bytes from a blob. Uploading data must be done from the {@link BlockBlobClient}, {@link PageBlobClient}, or {@link AppendBlobClient}.
+ * Reads a range of bytes from a blob. Uploading data must be done from the {@link BlockBlobClient}, {@link
+ * PageBlobClient}, or {@link AppendBlobClient}.
*
- * @param range
- * {@link BlobRange}
- * @param accessConditions
- * {@link BlobAccessConditions}
- * @param rangeGetContentMD5
- * Whether the contentMD5 for the specified blob range should be returned.
+ * @param range {@link BlobRange}
+ * @param accessConditions {@link BlobAccessConditions}
+ * @param rangeGetContentMD5 Whether the contentMD5 for the specified blob range should be returned.
* @param options {@link ReliableDownloadOptions}
- *
* @return A reactive response containing the blob data.
*/
- public Mono>> download(BlobRange range, BlobAccessConditions accessConditions,
- boolean rangeGetContentMD5, ReliableDownloadOptions options) {
- return blobAsyncRawClient
- .download(range, accessConditions, rangeGetContentMD5)
+ public Mono>> download(BlobRange range, BlobAccessConditions accessConditions, boolean rangeGetContentMD5, ReliableDownloadOptions options) {
+ return this.download(range, accessConditions, rangeGetContentMD5)
.map(response -> new SimpleResponse<>(
response.rawResponse(),
response.body(options).map(ByteBuf::nioBuffer).switchIfEmpty(Flux.just(ByteBuffer.allocate(0)))));
}
+ /**
+ * Reads a range of bytes from a blob. The response also includes the blob's properties and metadata. For more
+ * information, see the Azure Docs.
+ *
+ * Note that the response body has reliable download functionality built in, meaning that a failed download stream
+ * will be automatically retried. This behavior may be configured with {@link ReliableDownloadOptions}.
+ *
+ * @param range {@link BlobRange}
+ * @param accessConditions {@link BlobAccessConditions}
+ * @param rangeGetContentMD5 Whether the contentMD5 for the specified blob range should be returned.
+ * @return Emits the successful response.
+ * @apiNote ## Sample Code \n [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=upload_download
+ * "Sample code for BlobAsyncClient.download")] \n For more samples, please see the [Samples
+ * file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
+ */
+ Mono download(BlobRange range, BlobAccessConditions accessConditions, boolean rangeGetContentMD5) {
+ range = range == null ? new BlobRange(0) : range;
+ Boolean getMD5 = rangeGetContentMD5 ? rangeGetContentMD5 : null;
+ accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions;
+ HTTPGetterInfo info = new HTTPGetterInfo()
+ .offset(range.offset())
+ .count(range.count())
+ .eTag(accessConditions.modifiedAccessConditions().ifMatch());
+
+ // TODO: range is BlobRange but expected as String
+ // TODO: figure out correct response
+ return postProcessResponse(this.azureBlobStorage.blobs().downloadWithRestResponseAsync(
+ null, null, snapshot, null, null, range.toHeaderValue(), getMD5,
+ null, null, null, null,
+ accessConditions.leaseAccessConditions(), accessConditions.modifiedAccessConditions(), Context.NONE))
+ // Convert the autorest response to a DownloadAsyncResponse, which enable reliable download.
+ .map(response -> {
+ // If there wasn't an etag originally specified, lock on the one returned.
+ info.eTag(response.deserializedHeaders().eTag());
+ return new DownloadAsyncResponse(response, info,
+ // In the event of a stream failure, make a new request to pick up where we left off.
+ newInfo ->
+ this.download(new BlobRange(newInfo.offset(), newInfo.count()),
+ new BlobAccessConditions().modifiedAccessConditions(
+ new ModifiedAccessConditions().ifMatch(info.eTag())), false));
+ });
+ }
+
/**
* Downloads the entire blob into a file specified by the path. The file will be created if it doesn't exist.
- * Uploading data must be done from the {@link BlockBlobClient}, {@link PageBlobClient}, or {@link AppendBlobClient}.
+ * Uploading data must be done from the {@link BlockBlobClient}, {@link PageBlobClient}, or {@link
+ * AppendBlobClient}.
*
* This method makes an extra HTTP call to get the length of the blob in the beginning. To avoid this extra call,
* use the other overload providing the {@link BlobRange} parameter.
@@ -316,21 +368,17 @@ public Mono downloadToFile(String filePath) {
/**
* Downloads a range of bytes blob into a file specified by the path. The file will be created if it doesn't exist.
- * Uploading data must be done from the {@link BlockBlobClient}, {@link PageBlobClient}, or {@link AppendBlobClient}.
+ * Uploading data must be done from the {@link BlockBlobClient}, {@link PageBlobClient}, or {@link
+ * AppendBlobClient}.
*
* This method makes an extra HTTP call to get the length of the blob in the beginning. To avoid this extra call,
* provide the {@link BlobRange} parameter.
*
- * @param filePath
- * A non-null {@link OutputStream} instance where the downloaded data will be written.
- * @param range
- * {@link BlobRange}
- * @param blockSize
- * the size of a chunk to download at a time, in bytes
- * @param accessConditions
- * {@link BlobAccessConditions}
- * @param rangeGetContentMD5
- * Whether the contentMD5 for the specified blob range should be returned.
+ * @param filePath A non-null {@link OutputStream} instance where the downloaded data will be written.
+ * @param range {@link BlobRange}
+ * @param blockSize the size of a chunk to download at a time, in bytes
+ * @param accessConditions {@link BlobAccessConditions}
+ * @param rangeGetContentMD5 Whether the contentMD5 for the specified blob range should be returned.
* @param options {@link ReliableDownloadOptions}
* @return An empty response
* @throws IllegalArgumentException If {@code blockSize} is less than 0 or greater than 100MB.
@@ -346,8 +394,7 @@ public Mono downloadToFile(String filePath, BlobRange range, Integer block
channel -> Mono.justOrEmpty(range)
.switchIfEmpty(getFullBlobRange(accessConditions))
.flatMapMany(rg -> Flux.fromIterable(sliceBlobRange(rg, blockSize)))
- .flatMap(chunk -> blobAsyncRawClient
- .download(chunk, accessConditions, rangeGetContentMD5)
+ .flatMap(chunk -> this.download(chunk, accessConditions, rangeGetContentMD5)
.subscribeOn(Schedulers.elastic())
.flatMap(dar -> FluxUtil.bytebufStreamToFile(dar.body(options), channel, chunk.offset() - (range == null ? 0 : range.offset()))))
.then(), this::downloadToFileCleanup);
@@ -393,8 +440,7 @@ private List sliceBlobRange(BlobRange blobRange, Integer blockSize) {
/**
* Deletes the specified blob or snapshot. Note that deleting a blob also deletes all its snapshots.
*
- * @return
- * A reactive response signalling completion.
+ * @return A reactive response signalling completion.
*/
public Mono delete() {
return this.delete(null, null);
@@ -403,28 +449,26 @@ public Mono delete() {
/**
* Deletes the specified blob or snapshot. Note that deleting a blob also deletes all its snapshots.
*
- * @param deleteBlobSnapshotOptions
- * Specifies the behavior for deleting the snapshots on this blob. {@code Include} will delete the base blob
- * and all snapshots. {@code Only} will delete only the snapshots. If a snapshot is being deleted, you must
- * pass null.
- * @param accessConditions
- * {@link BlobAccessConditions}
- *
- * @return
- * A reactive response signalling completion.
+ * @param deleteBlobSnapshotOptions Specifies the behavior for deleting the snapshots on this blob. {@code Include}
+ * will delete the base blob and all snapshots. {@code Only} will delete only the snapshots. If a snapshot is being
+ * deleted, you must pass null.
+ * @param accessConditions {@link BlobAccessConditions}
+ * @return A reactive response signalling completion.
*/
- public Mono delete(DeleteSnapshotsOptionType deleteBlobSnapshotOptions,
- BlobAccessConditions accessConditions) {
- return blobAsyncRawClient
- .delete(deleteBlobSnapshotOptions, accessConditions)
+ public Mono delete(DeleteSnapshotsOptionType deleteBlobSnapshotOptions, BlobAccessConditions accessConditions) {
+ accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions;
+
+ return postProcessResponse(this.azureBlobStorage.blobs().deleteWithRestResponseAsync(
+ null, null, snapshot, null, null, deleteBlobSnapshotOptions,
+ null, accessConditions.leaseAccessConditions(), accessConditions.modifiedAccessConditions(),
+ Context.NONE))
.map(VoidResponse::new);
}
/**
* Returns the blob's metadata and properties.
*
- * @return
- * A reactive response containing the blob properties and metadata.
+ * @return A reactive response containing the blob properties and metadata.
*/
public Mono> getProperties() {
return this.getProperties(null);
@@ -433,93 +477,87 @@ public Mono> getProperties() {
/**
* Returns the blob's metadata and properties.
*
- * @param accessConditions
- * {@link BlobAccessConditions}
- *
- * @return
- * A reactive response containing the blob properties and metadata.
+ * @param accessConditions {@link BlobAccessConditions}
+ * @return A reactive response containing the blob properties and metadata.
*/
public Mono> getProperties(BlobAccessConditions accessConditions) {
- return blobAsyncRawClient
- .getProperties(accessConditions)
+ accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions;
+
+ return postProcessResponse(this.azureBlobStorage.blobs().getPropertiesWithRestResponseAsync(
+ null, null, snapshot, null, null, null,
+ null, null, null, accessConditions.leaseAccessConditions(),
+ accessConditions.modifiedAccessConditions(), Context.NONE))
.map(rb -> new SimpleResponse<>(rb, new BlobProperties(rb.deserializedHeaders())));
}
/**
- * Changes a blob's HTTP header properties. if only one HTTP header is updated, the
- * others will all be erased. In order to preserve existing values, they must be
- * passed alongside the header being changed. For more information, see the
+ * Changes a blob's HTTP header properties. if only one HTTP header is updated, the others will all be erased. In
+ * order to preserve existing values, they must be passed alongside the header being changed. For more information,
+ * see the
* Azure Docs.
*
- * @param headers
- * {@link BlobHTTPHeaders}
- *
- * @return
- * A reactive response signalling completion.
+ * @param headers {@link BlobHTTPHeaders}
+ * @return A reactive response signalling completion.
*/
public Mono setHTTPHeaders(BlobHTTPHeaders headers) {
return this.setHTTPHeaders(headers, null);
}
/**
- * Changes a blob's HTTP header properties. if only one HTTP header is updated, the
- * others will all be erased. In order to preserve existing values, they must be
- * passed alongside the header being changed. For more information, see the
+ * Changes a blob's HTTP header properties. if only one HTTP header is updated, the others will all be erased. In
+ * order to preserve existing values, they must be passed alongside the header being changed. For more information,
+ * see the
* Azure Docs.
*
- * @param headers
- * {@link BlobHTTPHeaders}
- * @param accessConditions
- * {@link BlobAccessConditions}
- *
- * @return
- * A reactive response signalling completion.
+ * @param headers {@link BlobHTTPHeaders}
+ * @param accessConditions {@link BlobAccessConditions}
+ * @return A reactive response signalling completion.
*/
public Mono setHTTPHeaders(BlobHTTPHeaders headers, BlobAccessConditions accessConditions) {
- return blobAsyncRawClient
- .setHTTPHeaders(headers, accessConditions)
+ accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions;
+
+ return postProcessResponse(this.azureBlobStorage.blobs().setHTTPHeadersWithRestResponseAsync(
+ null, null, null, null, headers,
+ accessConditions.leaseAccessConditions(), accessConditions.modifiedAccessConditions(), Context.NONE))
.map(VoidResponse::new);
}
/**
- * Changes a blob's metadata. The specified metadata in this method will replace existing
- * metadata. If old values must be preserved, they must be downloaded and included in the
- * call to this method. For more information, see the Azure Docs.
- *
- * @param metadata
- * {@link Metadata}
+ * Changes a blob's metadata. The specified metadata in this method will replace existing metadata. If old values
+ * must be preserved, they must be downloaded and included in the call to this method. For more information, see the
+ * Azure Docs.
*
- * @return
- * A reactive response signalling completion.
+ * @param metadata {@link Metadata}
+ * @return A reactive response signalling completion.
*/
public Mono setMetadata(Metadata metadata) {
return this.setMetadata(metadata, null);
}
/**
- * Changes a blob's metadata. The specified metadata in this method will replace existing
- * metadata. If old values must be preserved, they must be downloaded and included in the
- * call to this method. For more information, see the Azure Docs.
- *
- * @param metadata
- * {@link Metadata}
- * @param accessConditions
- * {@link BlobAccessConditions}
+ * Changes a blob's metadata. The specified metadata in this method will replace existing metadata. If old values
+ * must be preserved, they must be downloaded and included in the call to this method. For more information, see the
+ * Azure Docs.
*
- * @return
- * A reactive response signalling completion.
+ * @param metadata {@link Metadata}
+ * @param accessConditions {@link BlobAccessConditions}
+ * @return A reactive response signalling completion.
*/
public Mono setMetadata(Metadata metadata, BlobAccessConditions accessConditions) {
- return blobAsyncRawClient
- .setMetadata(metadata, accessConditions)
+ metadata = metadata == null ? new Metadata() : metadata;
+ accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions;
+
+ return postProcessResponse(this.azureBlobStorage.blobs().setMetadataWithRestResponseAsync(
+ null, null, null, metadata, null, null,
+ null, null, accessConditions.leaseAccessConditions(),
+ accessConditions.modifiedAccessConditions(), Context.NONE))
.map(VoidResponse::new);
}
/**
* Creates a read-only snapshot of a blob.
*
- * @return
- * A reactive response containing the ID of the new snapshot.
+ * @return A reactive response containing the ID of the new snapshot.
*/
public Mono> createSnapshot() {
return this.createSnapshot(null, null);
@@ -528,30 +566,29 @@ public Mono> createSnapshot() {
/**
* Creates a read-only snapshot of a blob.
*
- * @param metadata
- * {@link Metadata}
- * @param accessConditions
- * {@link BlobAccessConditions}
- *
- * @return
- * A reactive response containing the ID of the new snapshot.
+ * @param metadata {@link Metadata}
+ * @param accessConditions {@link BlobAccessConditions}
+ * @return A reactive response containing the ID of the new snapshot.
*/
public Mono> createSnapshot(Metadata metadata, BlobAccessConditions accessConditions) {
- return blobAsyncRawClient
- .createSnapshot(metadata, accessConditions)
+ metadata = metadata == null ? new Metadata() : metadata;
+ accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions;
+
+ return postProcessResponse(this.azureBlobStorage.blobs().createSnapshotWithRestResponseAsync(
+ null, null, null, metadata, null, null,
+ null, null, accessConditions.modifiedAccessConditions(),
+ accessConditions.leaseAccessConditions(), Context.NONE))
.map(rb -> new SimpleResponse<>(rb, rb.deserializedHeaders().snapshot()));
}
/**
* Sets the tier on a blob. The operation is allowed on a page blob in a premium storage account or a block blob in
* a blob storage or GPV2 account. A premium page blob's tier determines the allowed size, IOPS, and bandwidth of
- * the blob. A block blob's tier determines the Hot/Cool/Archive storage type. This does not update the blob's etag.
+ * the blob. A block blob's tier determines the Hot/Cool/Archive storage type. This does not update the blob's
+ * etag.
*
- * @param tier
- * The new tier for the blob.
- *
- * @return
- * A reactive response signalling completion.
+ * @param tier The new tier for the blob.
+ * @return A reactive response signalling completion.
*/
public Mono setTier(AccessTier tier) {
return this.setTier(tier, null);
@@ -560,32 +597,30 @@ public Mono setTier(AccessTier tier) {
/**
* Sets the tier on a blob. The operation is allowed on a page blob in a premium storage account or a block blob in
* a blob storage or GPV2 account. A premium page blob's tier determines the allowed size, IOPS, and bandwidth of
- * the blob. A block blob's tier determines the Hot/Cool/Archive storage type. This does not update the blob's etag.
- *
- * @param tier
- * The new tier for the blob.
- * @param leaseAccessConditions
- * By setting lease access conditions, requests will fail if the provided lease does not match the active
- * lease on the blob.
+ * the blob. A block blob's tier determines the Hot/Cool/Archive storage type. This does not update the blob's
+ * etag.
*
- * @return
- * A reactive response signalling completion.
+ * @param tier The new tier for the blob.
+ * @param leaseAccessConditions By setting lease access conditions, requests will fail if the provided lease does
+ * not match the active lease on the blob.
+ * @return A reactive response signalling completion.
*/
public Mono setTier(AccessTier tier, LeaseAccessConditions leaseAccessConditions) {
- return blobAsyncRawClient
- .setTier(tier, leaseAccessConditions)
+ Utility.assertNotNull("tier", tier);
+
+ return postProcessResponse(this.azureBlobStorage.blobs().setTierWithRestResponseAsync(
+ null, null, tier, null, null, leaseAccessConditions, Context.NONE))
.map(VoidResponse::new);
}
/**
* Undelete restores the content and metadata of a soft-deleted blob and/or any associated soft-deleted snapshots.
*
- * @return
- * A reactive response signalling completion.
+ * @return A reactive response signalling completion.
*/
public Mono undelete() {
- return blobAsyncRawClient
- .undelete()
+ return postProcessResponse(this.azureBlobStorage.blobs().undeleteWithRestResponseAsync(null,
+ null, Context.NONE))
.map(VoidResponse::new);
}
@@ -593,14 +628,10 @@ public Mono undelete() {
* Acquires a lease on the blob for write and delete operations. The lease duration must be between 15 to 60
* seconds, or infinite (-1).
*
- * @param proposedId
- * A {@code String} in any valid GUID format. May be null.
- * @param duration
- * The duration of the lease, in seconds, or negative one (-1) for a lease that
- * never expires. A non-infinite lease can be between 15 and 60 seconds.
- *
- * @return
- * A reactive response containing the lease ID.
+ * @param proposedId A {@code String} in any valid GUID format. May be null.
+ * @param duration The duration of the lease, in seconds, or negative one (-1) for a lease that never expires. A
+ * non-infinite lease can be between 15 and 60 seconds.
+ * @return A reactive response containing the lease ID.
*/
public Mono> acquireLease(String proposedId, int duration) {
return this.acquireLease(proposedId, duration, null);
@@ -610,33 +641,33 @@ public Mono> acquireLease(String proposedId, int duration) {
* Acquires a lease on the blob for write and delete operations. The lease duration must be between 15 to 60
* seconds, or infinite (-1).
*
- * @param proposedID
- * A {@code String} in any valid GUID format. May be null.
- * @param duration
- * The duration of the lease, in seconds, or negative one (-1) for a lease that
- * never expires. A non-infinite lease can be between 15 and 60 seconds.
- * @param modifiedAccessConditions
- * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used
- * to construct conditions related to when the blob was changed relative to the given request. The request
- * will fail if the specified condition is not satisfied.
- *
- * @return
- * A reactive response containing the lease ID.
+ * @param proposedID A {@code String} in any valid GUID format. May be null.
+ * @param duration The duration of the lease, in seconds, or negative one (-1) for a lease that never expires. A
+ * non-infinite lease can be between 15 and 60 seconds.
+ * @param modifiedAccessConditions Standard HTTP Access conditions related to the modification of data. ETag and
+ * LastModifiedTime are used to construct conditions related to when the blob was changed relative to the given
+ * request. The request will fail if the specified condition is not satisfied.
+ * @return A reactive response containing the lease ID.
+ * @throws IllegalArgumentException If {@code duration} is outside the bounds of 15 to 60 or isn't -1.
*/
public Mono> acquireLease(String proposedID, int duration, ModifiedAccessConditions modifiedAccessConditions) {
- return blobAsyncRawClient
- .acquireLease(proposedID, duration, modifiedAccessConditions)
+ if (!(duration == -1 || (duration >= 15 && duration <= 60))) {
+ // Throwing is preferred to Mono.error because this will error out immediately instead of waiting until
+ // subscription.
+ throw new IllegalArgumentException("Duration must be -1 or between 15 and 60.");
+ }
+
+ return postProcessResponse(this.azureBlobStorage.blobs().acquireLeaseWithRestResponseAsync(
+ null, null, null, duration, proposedID, null,
+ modifiedAccessConditions, Context.NONE))
.map(rb -> new SimpleResponse<>(rb, rb.deserializedHeaders().leaseId()));
}
/**
* Renews the blob's previously-acquired lease.
*
- * @param leaseID
- * The leaseId of the active lease on the blob.
- *
- * @return
- * A reactive response containing the renewed lease ID.
+ * @param leaseID The leaseId of the active lease on the blob.
+ * @return A reactive response containing the renewed lease ID.
*/
public Mono> renewLease(String leaseID) {
return this.renewLease(leaseID, null);
@@ -645,30 +676,23 @@ public Mono> renewLease(String leaseID) {
/**
* Renews the blob's previously-acquired lease.
*
- * @param leaseID
- * The leaseId of the active lease on the blob.
- * @param modifiedAccessConditions
- * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used
- * to construct conditions related to when the blob was changed relative to the given request. The request
- * will fail if the specified condition is not satisfied.
- *
- * @return
- * A reactive response containing the renewed lease ID.
+ * @param leaseID The leaseId of the active lease on the blob.
+ * @param modifiedAccessConditions Standard HTTP Access conditions related to the modification of data. ETag and
+ * LastModifiedTime are used to construct conditions related to when the blob was changed relative to the given
+ * request. The request will fail if the specified condition is not satisfied.
+ * @return A reactive response containing the renewed lease ID.
*/
public Mono> renewLease(String leaseID, ModifiedAccessConditions modifiedAccessConditions) {
- return blobAsyncRawClient
- .renewLease(leaseID, modifiedAccessConditions)
+ return postProcessResponse(this.azureBlobStorage.blobs().renewLeaseWithRestResponseAsync(null,
+ null, leaseID, null, null, modifiedAccessConditions, Context.NONE))
.map(rb -> new SimpleResponse<>(rb, rb.deserializedHeaders().leaseId()));
}
/**
* Releases the blob's previously-acquired lease.
*
- * @param leaseID
- * The leaseId of the active lease on the blob.
- *
- * @return
- * A reactive response signalling completion.
+ * @param leaseID The leaseId of the active lease on the blob.
+ * @return A reactive response signalling completion.
*/
public Mono releaseLease(String leaseID) {
return this.releaseLease(leaseID, null);
@@ -677,19 +701,15 @@ public Mono releaseLease(String leaseID) {
/**
* Releases the blob's previously-acquired lease.
*
- * @param leaseID
- * The leaseId of the active lease on the blob.
- * @param modifiedAccessConditions
- * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used
- * to construct conditions related to when the blob was changed relative to the given request. The request
- * will fail if the specified condition is not satisfied.
- *
- * @return
- * A reactive response signalling completion.
+ * @param leaseID The leaseId of the active lease on the blob.
+ * @param modifiedAccessConditions Standard HTTP Access conditions related to the modification of data. ETag and
+ * LastModifiedTime are used to construct conditions related to when the blob was changed relative to the given
+ * request. The request will fail if the specified condition is not satisfied.
+ * @return A reactive response signalling completion.
*/
public Mono releaseLease(String leaseID, ModifiedAccessConditions modifiedAccessConditions) {
- return blobAsyncRawClient
- .releaseLease(leaseID, modifiedAccessConditions)
+ return postProcessResponse(this.azureBlobStorage.blobs().releaseLeaseWithRestResponseAsync(null,
+ null, leaseID, null, null, modifiedAccessConditions, Context.NONE))
.map(VoidResponse::new);
}
@@ -697,8 +717,7 @@ public Mono releaseLease(String leaseID, ModifiedAccessConditions
* BreakLease breaks the blob's previously-acquired lease (if it exists). Pass the LeaseBreakDefault (-1) constant
* to break a fixed-duration lease when it expires or an infinite lease immediately.
*
- * @return
- * A reactive response containing the remaining time in the broken lease in seconds.
+ * @return A reactive response containing the remaining time in the broken lease in seconds.
*/
public Mono> breakLease() {
return this.breakLease(null, null);
@@ -708,70 +727,253 @@ public Mono> breakLease() {
* BreakLease breaks the blob's previously-acquired lease (if it exists). Pass the LeaseBreakDefault (-1) constant
* to break a fixed-duration lease when it expires or an infinite lease immediately.
*
- * @param breakPeriodInSeconds
- * An optional {@code Integer} representing the proposed duration of seconds that the lease should continue
- * before it is broken, between 0 and 60 seconds. This break period is only used if it is shorter than the
- * time remaining on the lease. If longer, the time remaining on the lease is used. A new lease will not be
- * available before the break period has expired, but the lease may be held for longer than the break
- * period.
- * @param modifiedAccessConditions
- * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used
- * to construct conditions related to when the blob was changed relative to the given request. The request
- * will fail if the specified condition is not satisfied.
- *
- * @return
- * A reactive response containing the remaining time in the broken lease in seconds.
+ * @param breakPeriodInSeconds An optional {@code Integer} representing the proposed duration of seconds that the
+ * lease should continue before it is broken, between 0 and 60 seconds. This break period is only used if it is
+ * shorter than the time remaining on the lease. If longer, the time remaining on the lease is used. A new lease
+ * will not be available before the break period has expired, but the lease may be held for longer than the break
+ * period.
+ * @param modifiedAccessConditions Standard HTTP Access conditions related to the modification of data. ETag and
+ * LastModifiedTime are used to construct conditions related to when the blob was changed relative to the given
+ * request. The request will fail if the specified condition is not satisfied.
+ * @return A reactive response containing the remaining time in the broken lease in seconds.
*/
public Mono> breakLease(Integer breakPeriodInSeconds, ModifiedAccessConditions modifiedAccessConditions) {
- return blobAsyncRawClient
- .breakLease(breakPeriodInSeconds, modifiedAccessConditions)
+ return postProcessResponse(this.azureBlobStorage.blobs().breakLeaseWithRestResponseAsync(null,
+ null, null, breakPeriodInSeconds, null, modifiedAccessConditions, Context.NONE))
.map(rb -> new SimpleResponse<>(rb, rb.deserializedHeaders().leaseTime()));
}
/**
* ChangeLease changes the blob's lease ID.
*
- * @param leaseId
- * The leaseId of the active lease on the blob.
- * @param proposedID
- * A {@code String} in any valid GUID format.
- *
- * @return
- * A reactive response containing the new lease ID.
+ * @param leaseId The leaseId of the active lease on the blob.
+ * @param proposedID A {@code String} in any valid GUID format.
+ * @return A reactive response containing the new lease ID.
*/
public Mono> changeLease(String leaseId, String proposedID) {
return this.changeLease(leaseId, proposedID, null);
}
/**
- * ChangeLease changes the blob's lease ID. For more information, see the Azure Docs.
- *
- * @param leaseId
- * The leaseId of the active lease on the blob.
- * @param proposedID
- * A {@code String} in any valid GUID format.
- * @param modifiedAccessConditions
- * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used
- * to construct conditions related to when the blob was changed relative to the given request. The request
- * will fail if the specified condition is not satisfied.
+ * ChangeLease changes the blob's lease ID. For more information, see the Azure
+ * Docs.
*
+ * @param leaseId The leaseId of the active lease on the blob.
+ * @param proposedID A {@code String} in any valid GUID format.
+ * @param modifiedAccessConditions Standard HTTP Access conditions related to the modification of data. ETag and
+ * LastModifiedTime are used to construct conditions related to when the blob was changed relative to the given
+ * request. The request will fail if the specified condition is not satisfied.
* @return A reactive response containing the new lease ID.
*/
public Mono> changeLease(String leaseId, String proposedID, ModifiedAccessConditions modifiedAccessConditions) {
- return blobAsyncRawClient
- .changeLease(leaseId, proposedID, modifiedAccessConditions)
+ return postProcessResponse(this.azureBlobStorage.blobs().changeLeaseWithRestResponseAsync(null,
+ null, leaseId, proposedID, null, null, modifiedAccessConditions, Context.NONE))
.map(rb -> new SimpleResponse<>(rb, rb.deserializedHeaders().leaseId()));
}
/**
- * Returns the sku name and account kind for the account. For more information, please see the Azure Docs.
+ * Returns the sku name and account kind for the account. For more information, please see the Azure Docs.
*
* @return a reactor response containing the sku name and account kind.
*/
// TODO (unknown): determine this return type
public Mono> getAccountInfo() {
- return blobAsyncRawClient
- .getAccountInfo()
+ return postProcessResponse(
+ this.azureBlobStorage.blobs().getAccountInfoWithRestResponseAsync(null, null, Context.NONE))
.map(rb -> new SimpleResponse<>(rb, new StorageAccountInfo(rb.deserializedHeaders())));
}
+
+ /**
+ * Generates a user delegation SAS with the specified parameters
+ *
+ * @param userDelegationKey The {@code UserDelegationKey} user delegation key for the SAS
+ * @param accountName The {@code String} account name for the SAS
+ * @param permissions The {@code ContainerSASPermissions} permission for the SAS
+ * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS
+ * @return A string that represents the SAS token
+ */
+ public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, String accountName,
+ BlobSASPermission permissions, OffsetDateTime expiryTime) {
+ return this.generateUserDelegationSAS(userDelegationKey, accountName, permissions, expiryTime, null /*
+ startTime */, null /* version */, null /*sasProtocol */, null /* ipRange */, null /* cacheControl */, null
+ /*contentDisposition */, null /* contentEncoding */, null /* contentLanguage */, null /* contentType */);
+ }
+
+ /**
+ * Generates a user delegation SAS token with the specified parameters
+ *
+ * @param userDelegationKey The {@code UserDelegationKey} user delegation key for the SAS
+ * @param accountName The {@code String} account name for the SAS
+ * @param permissions The {@code ContainerSASPermissions} permission for the SAS
+ * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS
+ * @param startTime An optional {@code OffsetDateTime} start time for the SAS
+ * @param version An optional {@code String} version for the SAS
+ * @param sasProtocol An optional {@code SASProtocol} protocol for the SAS
+ * @param ipRange An optional {@code IPRange} ip address range for the SAS
+ * @return A string that represents the SAS token
+ */
+ public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, String accountName,
+ BlobSASPermission permissions, OffsetDateTime expiryTime, OffsetDateTime startTime, String version,
+ SASProtocol sasProtocol, IPRange ipRange) {
+ return this.generateUserDelegationSAS(userDelegationKey, accountName, permissions, expiryTime, startTime,
+ version, sasProtocol, ipRange, null /* cacheControl */, null /* contentDisposition */, null /*
+ contentEncoding */, null /* contentLanguage */, null /* contentType */);
+ }
+
+ /**
+ * Generates a user delegation SAS token with the specified parameters
+ *
+ * @param userDelegationKey The {@code UserDelegationKey} user delegation key for the SAS
+ * @param accountName The {@code String} account name for the SAS
+ * @param permissions The {@code ContainerSASPermissions} permission for the SAS
+ * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS
+ * @param startTime An optional {@code OffsetDateTime} start time for the SAS
+ * @param version An optional {@code String} version for the SAS
+ * @param sasProtocol An optional {@code SASProtocol} protocol for the SAS
+ * @param ipRange An optional {@code IPRange} ip address range for the SAS
+ * @param cacheControl An optional {@code String} cache-control header for the SAS.
+ * @param contentDisposition An optional {@code String} content-disposition header for the SAS.
+ * @param contentEncoding An optional {@code String} content-encoding header for the SAS.
+ * @param contentLanguage An optional {@code String} content-language header for the SAS.
+ * @param contentType An optional {@code String} content-type header for the SAS.
+ * @return A string that represents the SAS token
+ */
+ public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, String accountName,
+ BlobSASPermission permissions, OffsetDateTime expiryTime, OffsetDateTime startTime, String version,
+ SASProtocol sasProtocol, IPRange ipRange, String cacheControl, String contentDisposition,
+ String contentEncoding, String contentLanguage, String contentType) {
+
+ ServiceSASSignatureValues serviceSASSignatureValues = new ServiceSASSignatureValues(version, sasProtocol,
+ startTime, expiryTime, permissions == null ? null : permissions.toString(), ipRange, null /* identifier*/,
+ cacheControl, contentDisposition, contentEncoding, contentLanguage, contentType);
+
+ ServiceSASSignatureValues values = configureServiceSASSignatureValues(serviceSASSignatureValues, accountName);
+
+ SASQueryParameters sasQueryParameters = values.generateSASQueryParameters(userDelegationKey);
+
+ return sasQueryParameters.encode();
+ }
+
+ /**
+ * Generates a SAS token with the specified parameters
+ *
+ * @param permissions The {@code ContainerSASPermissions} permission for the SAS
+ * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS
+ * @return A string that represents the SAS token
+ */
+ public String generateSAS(BlobSASPermission permissions, OffsetDateTime expiryTime) {
+ return this.generateSAS(null, permissions, expiryTime, null /* startTime */, /* identifier */ null /*
+ version */, null /* sasProtocol */, null /* ipRange */, null /* cacheControl */, null /* contentLanguage*/,
+ null /* contentEncoding */, null /* contentLanguage */, null /* contentType */);
+ }
+
+ /**
+ * Generates a SAS token with the specified parameters
+ *
+ * @param identifier The {@code String} name of the access policy on the container this SAS references if any
+ * @return A string that represents the SAS token
+ */
+ public String generateSAS(String identifier) {
+ return this.generateSAS(identifier, null /* permissions */, null /* expiryTime */, null /* startTime */,
+ null /* version */, null /* sasProtocol */, null /* ipRange */, null /* cacheControl */, null /*
+ contentLanguage*/, null /* contentEncoding */, null /* contentLanguage */, null /* contentType */);
+ }
+
+ /**
+ * Generates a SAS token with the specified parameters
+ *
+ * @param identifier The {@code String} name of the access policy on the container this SAS references if any
+ * @param permissions The {@code ContainerSASPermissions} permission for the SAS
+ * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS
+ * @param startTime An optional {@code OffsetDateTime} start time for the SAS
+ * @param version An optional {@code String} version for the SAS
+ * @param sasProtocol An optional {@code SASProtocol} protocol for the SAS
+ * @param ipRange An optional {@code IPRange} ip address range for the SAS
+ * @return A string that represents the SAS token
+ */
+ public String generateSAS(String identifier, BlobSASPermission permissions, OffsetDateTime expiryTime,
+ OffsetDateTime startTime, String version, SASProtocol sasProtocol, IPRange ipRange) {
+ return this.generateSAS(identifier, permissions, expiryTime, startTime, version, sasProtocol, ipRange, null
+ /* cacheControl */, null /* contentLanguage*/, null /* contentEncoding */, null /* contentLanguage */,
+ null /* contentType */);
+ }
+
+ /**
+ * Generates a SAS token with the specified parameters
+ *
+ * @param identifier The {@code String} name of the access policy on the container this SAS references if any
+ * @param permissions The {@code ContainerSASPermissions} permission for the SAS
+ * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS
+ * @param startTime An optional {@code OffsetDateTime} start time for the SAS
+ * @param version An optional {@code String} version for the SAS
+ * @param sasProtocol An optional {@code SASProtocol} protocol for the SAS
+ * @param ipRange An optional {@code IPRange} ip address range for the SAS
+ * @param cacheControl An optional {@code String} cache-control header for the SAS.
+ * @param contentDisposition An optional {@code String} content-disposition header for the SAS.
+ * @param contentEncoding An optional {@code String} content-encoding header for the SAS.
+ * @param contentLanguage An optional {@code String} content-language header for the SAS.
+ * @param contentType An optional {@code String} content-type header for the SAS.
+ * @return A string that represents the SAS token
+ */
+ public String generateSAS(String identifier, BlobSASPermission permissions, OffsetDateTime expiryTime,
+ OffsetDateTime startTime, String version, SASProtocol sasProtocol, IPRange ipRange, String cacheControl,
+ String contentDisposition, String contentEncoding, String contentLanguage, String contentType) {
+
+ ServiceSASSignatureValues serviceSASSignatureValues = new ServiceSASSignatureValues(version, sasProtocol,
+ startTime, expiryTime, permissions == null ? null : permissions.toString(), ipRange, identifier,
+ cacheControl, contentDisposition, contentEncoding, contentLanguage, contentType);
+
+ SharedKeyCredential sharedKeyCredential =
+ Utility.getSharedKeyCredential(this.azureBlobStorage.httpPipeline());
+
+ Utility.assertNotNull("sharedKeyCredential", sharedKeyCredential);
+
+ ServiceSASSignatureValues values = configureServiceSASSignatureValues(serviceSASSignatureValues,
+ sharedKeyCredential.accountName());
+
+ SASQueryParameters sasQueryParameters = values.generateSASQueryParameters(sharedKeyCredential);
+
+ return sasQueryParameters.encode();
+ }
+
+ /**
+ * Sets serviceSASSignatureValues parameters dependent on the current blob type
+ */
+ ServiceSASSignatureValues configureServiceSASSignatureValues(ServiceSASSignatureValues serviceSASSignatureValues,
+ String accountName) {
+
+ // Set canonical name
+ serviceSASSignatureValues.canonicalName(this.azureBlobStorage.url(), accountName);
+
+ // Set snapshotId
+ serviceSASSignatureValues.snapshotId(getSnapshotId());
+
+ // Set resource
+ if (isSnapshot()) {
+ serviceSASSignatureValues.resource(Constants.UrlConstants.SAS_BLOB_SNAPSHOT_CONSTANT);
+ } else {
+ serviceSASSignatureValues.resource(Constants.UrlConstants.SAS_BLOB_CONSTANT);
+ }
+
+ return serviceSASSignatureValues;
+ }
+
+ /**
+ * Gets the snapshotId for a blob resource
+ *
+ * @return A string that represents the snapshotId of the snapshot blob
+ */
+ public String getSnapshotId() {
+ return this.snapshot;
+ }
+
+ /**
+ * Determines if a blob is a snapshot
+ *
+ * @return A boolean that indicates if a blob is a snapshot
+ */
+ public boolean isSnapshot() {
+ return this.snapshot != null;
+ }
}
diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobAsyncRawClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobAsyncRawClient.java
deleted file mode 100644
index 002ba761a3bf8..0000000000000
--- a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobAsyncRawClient.java
+++ /dev/null
@@ -1,766 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package com.azure.storage.blob;
-
-import com.azure.core.util.Context;
-import com.azure.storage.blob.implementation.AzureBlobStorageImpl;
-import com.azure.storage.blob.models.AccessTier;
-import com.azure.storage.blob.models.BlobAccessConditions;
-import com.azure.storage.blob.models.BlobHTTPHeaders;
-import com.azure.storage.blob.models.BlobRange;
-import com.azure.storage.blob.models.BlobStartCopyFromURLHeaders;
-import com.azure.storage.blob.models.BlobsAbortCopyFromURLResponse;
-import com.azure.storage.blob.models.BlobsAcquireLeaseResponse;
-import com.azure.storage.blob.models.BlobsBreakLeaseResponse;
-import com.azure.storage.blob.models.BlobsChangeLeaseResponse;
-import com.azure.storage.blob.models.BlobsCopyFromURLResponse;
-import com.azure.storage.blob.models.BlobsCreateSnapshotResponse;
-import com.azure.storage.blob.models.BlobsDeleteResponse;
-import com.azure.storage.blob.models.BlobsGetAccountInfoResponse;
-import com.azure.storage.blob.models.BlobsGetPropertiesResponse;
-import com.azure.storage.blob.models.BlobsReleaseLeaseResponse;
-import com.azure.storage.blob.models.BlobsRenewLeaseResponse;
-import com.azure.storage.blob.models.BlobsSetHTTPHeadersResponse;
-import com.azure.storage.blob.models.BlobsSetMetadataResponse;
-import com.azure.storage.blob.models.BlobsSetTierResponse;
-import com.azure.storage.blob.models.BlobsStartCopyFromURLResponse;
-import com.azure.storage.blob.models.BlobsUndeleteResponse;
-import com.azure.storage.blob.models.DeleteSnapshotsOptionType;
-import com.azure.storage.blob.models.LeaseAccessConditions;
-import com.azure.storage.blob.models.Metadata;
-import com.azure.storage.blob.models.ModifiedAccessConditions;
-import com.azure.storage.blob.models.ReliableDownloadOptions;
-import com.azure.storage.blob.models.SourceModifiedAccessConditions;
-import reactor.core.publisher.Mono;
-
-import java.net.URL;
-
-import static com.azure.storage.blob.Utility.postProcessResponse;
-
-/**
- * Represents a URL to a blob of any type: block, append, or page. It may be obtained by direct construction or via the
- * create method on a {@link ContainerAsyncClient} object. This class does not hold any state about a particular blob but is
- * instead a convenient way of sending off appropriate requests to the resource on the service. Please refer to the
- * Azure Docs for more information.
- */
-class BlobAsyncRawClient {
-
- protected AzureBlobStorageImpl azureBlobStorage;
-
- final String snapshot;
-
- /**
- * Creates a {@code BlobAsyncRawClient} object pointing to the account specified by the URL and using the provided pipeline to
- * make HTTP requests..
- */
- BlobAsyncRawClient(AzureBlobStorageImpl azureBlobStorage, String snapshot) {
- this.azureBlobStorage = azureBlobStorage;
- this.snapshot = snapshot;
- }
-
- /**
- * Copies the data at the source URL to a blob. For more information, see the Azure Docs
- *
- * @param sourceURL
- * The source URL to copy from. URLs outside of Azure may only be copied to block blobs.
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=start_copy "Sample code for BlobAsyncRawClient.startCopyFromURL")] \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=start_copy_helper "Helper for start_copy sample.")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono startCopyFromURL(URL sourceURL) {
- return this.startCopyFromURL(sourceURL, null, null, null);
- }
-
- /**
- * Copies the data at the source URL to a blob. For more information, see the Azure Docs
- *
- * @param sourceURL
- * The source URL to copy from. URLs outside of Azure may only be copied to block blobs.
- * @param metadata
- * {@link Metadata}
- * @param sourceModifiedAccessConditions
- * {@link ModifiedAccessConditions} against the source. Standard HTTP Access conditions related to the
- * modification of data. ETag and LastModifiedTime are used to construct conditions related to when the blob
- * was changed relative to the given request. The request will fail if the specified condition is not
- * satisfied.
- * @param destAccessConditions
- * {@link BlobAccessConditions} against the destination.
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=start_copy "Sample code for BlobAsyncRawClient.startCopyFromURL")] \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=start_copy_helper "Helper for start_copy sample.")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono startCopyFromURL(URL sourceURL, Metadata metadata,
- ModifiedAccessConditions sourceModifiedAccessConditions, BlobAccessConditions destAccessConditions) {
- metadata = metadata == null ? new Metadata() : metadata;
- sourceModifiedAccessConditions = sourceModifiedAccessConditions == null
- ? new ModifiedAccessConditions() : sourceModifiedAccessConditions;
- destAccessConditions = destAccessConditions == null ? new BlobAccessConditions() : destAccessConditions;
-
- // We want to hide the SourceAccessConditions type from the user for consistency's sake, so we convert here.
- SourceModifiedAccessConditions sourceConditions = new SourceModifiedAccessConditions()
- .sourceIfModifiedSince(sourceModifiedAccessConditions.ifModifiedSince())
- .sourceIfUnmodifiedSince(sourceModifiedAccessConditions.ifUnmodifiedSince())
- .sourceIfMatch(sourceModifiedAccessConditions.ifMatch())
- .sourceIfNoneMatch(sourceModifiedAccessConditions.ifNoneMatch());
-
- return postProcessResponse(this.azureBlobStorage.blobs().startCopyFromURLWithRestResponseAsync(
- null, null, sourceURL, null, metadata, null, sourceConditions,
- destAccessConditions.modifiedAccessConditions(), destAccessConditions.leaseAccessConditions(), Context.NONE));
- }
-
- /**
- * Stops a pending copy that was previously started and leaves a destination blob with 0 length and metadata. For
- * more information, see the Azure Docs.
- *
- * @param copyId
- * The id of the copy operation to abort. Returned as the {@code copyId} field on the {@link
- * BlobStartCopyFromURLHeaders} object.
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=abort_copy "Sample code for BlobAsyncRawClient.abortCopyFromURL")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono abortCopyFromURL(String copyId) {
- return this.abortCopyFromURL(copyId, null);
- }
-
- /**
- * Stops a pending copy that was previously started and leaves a destination blob with 0 length and metadata. For
- * more information, see the Azure Docs.
- *
- * @param copyId
- * The id of the copy operation to abort. Returned as the {@code copyId} field on the {@link
- * BlobStartCopyFromURLHeaders} object.
- * @param leaseAccessConditions
- * By setting lease access conditions, requests will fail if the provided lease does not match the active
- * lease on the blob.
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=abort_copy "Sample code for BlobAsyncRawClient.abortCopyFromURL")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono abortCopyFromURL(String copyId,
- LeaseAccessConditions leaseAccessConditions) {
- return postProcessResponse(this.azureBlobStorage.blobs().abortCopyFromURLWithRestResponseAsync(
- null, null, copyId, null, null, leaseAccessConditions, Context.NONE));
- }
-
- /**
- * Copies the data at the source URL to a blob and waits for the copy to complete before returning a response.
- * For more information, see the Azure Docs
- *
- * @param copySource
- * The source URL to copy from.
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=sync_copy "Sample code for BlobAsyncRawClient.copyFromURL")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono syncCopyFromURL(URL copySource) {
- return this.syncCopyFromURL(copySource, null, null, null);
- }
-
- /**
- * Copies the data at the source URL to a blob and waits for the copy to complete before returning a response.
- * For more information, see the Azure Docs
- *
- * @param copySource
- * The source URL to copy from. URLs outside of Azure may only be copied to block blobs.
- * @param metadata
- * {@link Metadata}
- * @param sourceModifiedAccessConditions
- * {@link ModifiedAccessConditions} against the source. Standard HTTP Access conditions related to the
- * modification of data. ETag and LastModifiedTime are used to construct conditions related to when the blob
- * was changed relative to the given request. The request will fail if the specified condition is not
- * satisfied.
- * @param destAccessConditions
- * {@link BlobAccessConditions} against the destination.
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=sync_copy "Sample code for BlobAsyncRawClient.copyFromURL")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono syncCopyFromURL(URL copySource, Metadata metadata,
- ModifiedAccessConditions sourceModifiedAccessConditions, BlobAccessConditions destAccessConditions) {
- metadata = metadata == null ? new Metadata() : metadata;
- sourceModifiedAccessConditions = sourceModifiedAccessConditions == null
- ? new ModifiedAccessConditions() : sourceModifiedAccessConditions;
- destAccessConditions = destAccessConditions == null ? new BlobAccessConditions() : destAccessConditions;
-
- // We want to hide the SourceAccessConditions type from the user for consistency's sake, so we convert here.
- SourceModifiedAccessConditions sourceConditions = new SourceModifiedAccessConditions()
- .sourceIfModifiedSince(sourceModifiedAccessConditions.ifModifiedSince())
- .sourceIfUnmodifiedSince(sourceModifiedAccessConditions.ifUnmodifiedSince())
- .sourceIfMatch(sourceModifiedAccessConditions.ifMatch())
- .sourceIfNoneMatch(sourceModifiedAccessConditions.ifNoneMatch());
-
- return postProcessResponse(this.azureBlobStorage.blobs().copyFromURLWithRestResponseAsync(
- null, null, copySource, null, metadata, null, sourceConditions,
- destAccessConditions.modifiedAccessConditions(), destAccessConditions.leaseAccessConditions(), Context.NONE));
- }
-
- /**
- * Reads a range of bytes from a blob. The response also includes the blob's properties and metadata. For more
- * information, see the Azure Docs.
- *
- * Note that the response body has reliable download functionality built in, meaning that a failed download stream
- * will be automatically retried. This behavior may be configured with {@link ReliableDownloadOptions}.
- *
- * @return Emits the successful response.
- * @apiNote ## Sample Code \n [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=upload_download
- * "Sample code for BlobAsyncRawClient.download")] \n For more samples, please see the [Samples
- * file](%https://github.com/Azure/azure-storage-java/blob/New-Storage-SDK-V10-Preview/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono download() {
- return this.download(null, null, false);
- }
-
- /**
- * Reads a range of bytes from a blob. The response also includes the blob's properties and metadata. For more
- * information, see the Azure Docs.
- *
- * Note that the response body has reliable download functionality built in, meaning that a failed download stream
- * will be automatically retried. This behavior may be configured with {@link ReliableDownloadOptions}.
- *
- * @param range
- * {@link BlobRange}
- * @param accessConditions
- * {@link BlobAccessConditions}
- * @param rangeGetContentMD5
- * Whether the contentMD5 for the specified blob range should be returned.
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=upload_download "Sample code for BlobAsyncRawClient.download")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono download(BlobRange range, BlobAccessConditions accessConditions,
- boolean rangeGetContentMD5) {
- range = range == null ? new BlobRange(0) : range;
- Boolean getMD5 = rangeGetContentMD5 ? rangeGetContentMD5 : null;
- accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions;
- HTTPGetterInfo info = new HTTPGetterInfo()
- .offset(range.offset())
- .count(range.count())
- .eTag(accessConditions.modifiedAccessConditions().ifMatch());
-
- // TODO: range is BlobRange but expected as String
- // TODO: figure out correct response
- return postProcessResponse(this.azureBlobStorage.blobs().downloadWithRestResponseAsync(
- null, null, snapshot, null, null, range.toHeaderValue(), getMD5,
- null, null, null, null,
- accessConditions.leaseAccessConditions(), accessConditions.modifiedAccessConditions(), Context.NONE))
- // Convert the autorest response to a DownloadAsyncResponse, which enable reliable download.
- .map(response -> {
- // If there wasn't an etag originally specified, lock on the one returned.
- info.eTag(response.deserializedHeaders().eTag());
- return new DownloadAsyncResponse(response, info,
- // In the event of a stream failure, make a new request to pick up where we left off.
- newInfo ->
- this.download(new BlobRange(newInfo.offset(), newInfo.count()),
- new BlobAccessConditions().modifiedAccessConditions(
- new ModifiedAccessConditions().ifMatch(info.eTag())), false));
- });
- }
-
- /**
- * Deletes the specified blob or snapshot. Note that deleting a blob also deletes all its snapshots. For more
- * information, see the Azure Docs.
- *
- * @return Emits the successful response.
- * @apiNote ## Sample Code \n [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blob_delete
- * "Sample code for BlobAsyncRawClient.delete")] \n For more samples, please see the [Samples
- * file](%https://github.com/Azure/azure-storage-java/blob/New-Storage-SDK-V10-Preview/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono delete() {
- return this.delete(null, null);
- }
-
- /**
- * Deletes the specified blob or snapshot. Note that deleting a blob also deletes all its snapshots. For more
- * information, see the Azure Docs.
- *
- * @param deleteBlobSnapshotOptions
- * Specifies the behavior for deleting the snapshots on this blob. {@code Include} will delete the base blob
- * and all snapshots. {@code Only} will delete only the snapshots. If a snapshot is being deleted, you must
- * pass null.
- * @param accessConditions
- * {@link BlobAccessConditions}
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blob_delete "Sample code for BlobAsyncRawClient.delete")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono delete(DeleteSnapshotsOptionType deleteBlobSnapshotOptions,
- BlobAccessConditions accessConditions) {
- accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions;
-
- return postProcessResponse(this.azureBlobStorage.blobs().deleteWithRestResponseAsync(
- null, null, snapshot, null, null, deleteBlobSnapshotOptions,
- null, accessConditions.leaseAccessConditions(), accessConditions.modifiedAccessConditions(),
- Context.NONE));
- }
-
- /**
- * Returns the blob's metadata and properties. For more information, see the Azure Docs.
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=properties_metadata "Sample code for BlobAsyncRawClient.getProperties")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono getProperties() {
- return this.getProperties(null);
- }
-
- /**
- * Returns the blob's metadata and properties. For more information, see the Azure Docs.
- *
- * @param accessConditions
- * {@link BlobAccessConditions}
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=properties_metadata "Sample code for BlobAsyncRawClient.getProperties")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono getProperties(BlobAccessConditions accessConditions) {
- accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions;
-
- return postProcessResponse(this.azureBlobStorage.blobs().getPropertiesWithRestResponseAsync(
- null, null, snapshot, null, null, null,
- null, null, null, accessConditions.leaseAccessConditions(),
- accessConditions.modifiedAccessConditions(), Context.NONE));
- }
-
- /**
- * Changes a blob's HTTP header properties. For more information, see the Azure
- * Docs.
- *
- * @param headers
- * {@link BlobHTTPHeaders}
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=properties_metadata "Sample code for BlobAsyncRawClient.setHTTPHeaders")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono setHTTPHeaders(BlobHTTPHeaders headers) {
- return this.setHTTPHeaders(headers, null);
- }
-
- /**
- * Changes a blob's HTTP header properties. For more information, see the Azure Docs.
- *
- * @param headers
- * {@link BlobHTTPHeaders}
- * @param accessConditions
- * {@link BlobAccessConditions}
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=properties_metadata "Sample code for BlobAsyncRawClient.setHTTPHeaders")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono setHTTPHeaders(BlobHTTPHeaders headers,
- BlobAccessConditions accessConditions) {
- accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions;
-
- return postProcessResponse(this.azureBlobStorage.blobs().setHTTPHeadersWithRestResponseAsync(
- null, null, null, null, headers,
- accessConditions.leaseAccessConditions(), accessConditions.modifiedAccessConditions(), Context.NONE));
- }
-
- /**
- * Changes a blob's metadata. For more information, see the Azure Docs.
- *
- * @param metadata
- * {@link Metadata}
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=properties_metadata "Sample code for BlobAsyncRawClient.setMetadata")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono setMetadata(Metadata metadata) {
- return this.setMetadata(metadata, null);
- }
-
- /**
- * Changes a blob's metadata. For more information, see the Azure Docs.
- *
- * @param metadata
- * {@link Metadata}
- * @param accessConditions
- * {@link BlobAccessConditions}
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=properties_metadata "Sample code for BlobAsyncRawClient.setMetadata")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono setMetadata(Metadata metadata, BlobAccessConditions accessConditions) {
- metadata = metadata == null ? new Metadata() : metadata;
- accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions;
-
- return postProcessResponse(this.azureBlobStorage.blobs().setMetadataWithRestResponseAsync(
- null, null, null, metadata, null, null,
- null, null, accessConditions.leaseAccessConditions(),
- accessConditions.modifiedAccessConditions(), Context.NONE));
- }
-
- /**
- * Creates a read-only snapshot of a blob. For more information, see the Azure Docs.
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=snapshot "Sample code for BlobAsyncRawClient.createSnapshot")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono createSnapshot() {
- return this.createSnapshot(null, null);
- }
-
- /**
- * Creates a read-only snapshot of a blob. For more information, see the Azure Docs.
- *
- * @param metadata
- * {@link Metadata}
- * @param accessConditions
- * {@link BlobAccessConditions}
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=snapshot "Sample code for BlobAsyncRawClient.createSnapshot")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono createSnapshot(Metadata metadata, BlobAccessConditions accessConditions) {
- metadata = metadata == null ? new Metadata() : metadata;
- accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions;
-
- return postProcessResponse(this.azureBlobStorage.blobs().createSnapshotWithRestResponseAsync(
- null, null, null, metadata, null, null,
- null, null, accessConditions.modifiedAccessConditions(),
- accessConditions.leaseAccessConditions(), Context.NONE));
- }
-
- /**
- * Sets the tier on a blob. The operation is allowed on a page blob in a premium storage account or a block blob in
- * a blob storage or GPV2 account. A premium page blob's tier determines the allowed size, IOPS, and bandwidth of
- * the blob. A block blob's tier determines the Hot/Cool/Archive storage type. This does not update the blob's etag.
- *
- * For detailed information about block blob level tiering see the Azure Docs.
- *
- * @param tier
- * The new tier for the blob.
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=tier "Sample code for BlobAsyncRawClient.setTier")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono setTier(AccessTier tier) {
- return this.setTier(tier, null);
- }
-
- /**
- * Sets the tier on a blob. The operation is allowed on a page blob in a premium storage account or a block blob in
- * a blob storage or GPV2 account. A premium page blob's tier determines the allowed size, IOPS, and bandwidth of
- * the blob. A block blob's tier determines the Hot/Cool/Archive storage type. This does not update the blob's etag.
- *
- * For detailed information about block blob level tiering see the Azure Docs.
- *
- * @param tier
- * The new tier for the blob.
- * @param leaseAccessConditions
- * By setting lease access conditions, requests will fail if the provided lease does not match the active
- * lease on the blob.
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=tier "Sample code for BlobAsyncRawClient.setTier")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono setTier(AccessTier tier, LeaseAccessConditions leaseAccessConditions) {
- Utility.assertNotNull("tier", tier);
-
- return postProcessResponse(this.azureBlobStorage.blobs().setTierWithRestResponseAsync(
- null, null, tier, null, null, leaseAccessConditions, Context.NONE));
- }
-
- /**
- * Undelete restores the content and metadata of a soft-deleted blob and/or any associated soft-deleted snapshots.
- * For more information, see the Azure Docs.
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=undelete "Sample code for BlobAsyncRawClient.undelete")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono undelete() {
- return postProcessResponse(this.azureBlobStorage.blobs().undeleteWithRestResponseAsync(null,
- null, Context.NONE));
- }
-
- /**
- * Acquires a lease on the blob for write and delete operations. The lease duration must be between 15 to 60
- * seconds, or infinite (-1). For more information, see the Azure Docs.
- *
- * @param proposedId
- * A {@code String} in any valid GUID format. May be null.
- * @param duration
- * The duration of the lease, in seconds, or negative one (-1) for a lease that
- * never expires. A non-infinite lease can be between 15 and 60 seconds.
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blob_lease "Sample code for BlobAsyncRawClient.acquireLease")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono acquireLease(String proposedId, int duration) {
- return this.acquireLease(proposedId, duration, null);
- }
-
- /**
- * Acquires a lease on the blob for write and delete operations. The lease duration must be between 15 to 60
- * seconds, or infinite (-1). For more information, see the Azure Docs.
- *
- * @param proposedID
- * A {@code String} in any valid GUID format. May be null.
- * @param duration
- * The duration of the lease, in seconds, or negative one (-1) for a lease that
- * never expires. A non-infinite lease can be between 15 and 60 seconds.
- * @param modifiedAccessConditions
- * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used
- * to construct conditions related to when the blob was changed relative to the given request. The request
- * will fail if the specified condition is not satisfied.
- *
- * @return Emits the successful response.
- * @throws IllegalArgumentException If {@code duration} is outside the bounds of 15 to 60 or isn't -1.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blob_lease "Sample code for BlobAsyncRawClient.acquireLease")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono acquireLease(String proposedID, int duration,
- ModifiedAccessConditions modifiedAccessConditions) {
- if (!(duration == -1 || (duration >= 15 && duration <= 60))) {
- // Throwing is preferred to Mono.error because this will error out immediately instead of waiting until
- // subscription.
- throw new IllegalArgumentException("Duration must be -1 or between 15 and 60.");
- }
-
- return postProcessResponse(this.azureBlobStorage.blobs().acquireLeaseWithRestResponseAsync(
- null, null, null, duration, proposedID, null,
- modifiedAccessConditions, Context.NONE));
- }
-
- /**
- * Renews the blob's previously-acquired lease. For more information, see the Azure Docs.
- *
- * @param leaseID
- * The leaseId of the active lease on the blob.
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blob_lease "Sample code for BlobAsyncRawClient.renewLease")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono renewLease(String leaseID) {
- return this.renewLease(leaseID, null);
- }
-
- /**
- * Renews the blob's previously-acquired lease. For more information, see the Azure Docs.
- *
- * @param leaseID
- * The leaseId of the active lease on the blob.
- * @param modifiedAccessConditions
- * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used
- * to construct conditions related to when the blob was changed relative to the given request. The request
- * will fail if the specified condition is not satisfied.
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blob_lease "Sample code for BlobAsyncRawClient.renewLease")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono renewLease(String leaseID, ModifiedAccessConditions modifiedAccessConditions) {
- return postProcessResponse(this.azureBlobStorage.blobs().renewLeaseWithRestResponseAsync(null,
- null, leaseID, null, null, modifiedAccessConditions, Context.NONE));
- }
-
- /**
- * Releases the blob's previously-acquired lease. For more information, see the Azure Docs.
- *
- * @param leaseID
- * The leaseId of the active lease on the blob.
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blob_lease "Sample code for BlobAsyncRawClient.releaseLease")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono releaseLease(String leaseID) {
- return this.releaseLease(leaseID, null);
- }
-
- /**
- * Releases the blob's previously-acquired lease. For more information, see the Azure Docs.
- *
- * @param leaseID
- * The leaseId of the active lease on the blob.
- * @param modifiedAccessConditions
- * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used
- * to construct conditions related to when the blob was changed relative to the given request. The request
- * will fail if the specified condition is not satisfied.
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blob_lease "Sample code for BlobAsyncRawClient.releaseLease")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono releaseLease(String leaseID,
- ModifiedAccessConditions modifiedAccessConditions) {
- return postProcessResponse(this.azureBlobStorage.blobs().releaseLeaseWithRestResponseAsync(null,
- null, leaseID, null, null, modifiedAccessConditions, Context.NONE));
- }
-
- /**
- * BreakLease breaks the blob's previously-acquired lease (if it exists). Pass the LeaseBreakDefault (-1) constant
- * to break a fixed-duration lease when it expires or an infinite lease immediately. For more information, see the
- * Azure Docs.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blob_lease "Sample code for BlobAsyncRawClient.breakLease")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/New-Storage-SDK-V10-Preview/src/test/java/com/microsoft/azure/storage/Samples.java)
- *
- * @return
- * Emits the successful response.
- */
- public Mono breakLease() {
- return this.breakLease(null, null);
- }
-
- /**
- * BreakLease breaks the blob's previously-acquired lease (if it exists). Pass the LeaseBreakDefault (-1) constant
- * to break a fixed-duration lease when it expires or an infinite lease immediately. For more information, see the
- * Azure Docs.
- *
- * @param breakPeriodInSeconds
- * An optional {@code Integer} representing the proposed duration of seconds that the lease should continue
- * before it is broken, between 0 and 60 seconds. This break period is only used if it is shorter than the
- * time remaining on the lease. If longer, the time remaining on the lease is used. A new lease will not be
- * available before the break period has expired, but the lease may be held for longer than the break
- * period.
- * @param modifiedAccessConditions
- * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used
- * to construct conditions related to when the blob was changed relative to the given request. The request
- * will fail if the specified condition is not satisfied.
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blob_lease "Sample code for BlobAsyncRawClient.breakLease")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono breakLease(Integer breakPeriodInSeconds,
- ModifiedAccessConditions modifiedAccessConditions) {
- return postProcessResponse(this.azureBlobStorage.blobs().breakLeaseWithRestResponseAsync(null,
- null, null, breakPeriodInSeconds, null, modifiedAccessConditions, Context.NONE));
- }
-
- /**
- * ChangeLease changes the blob's lease ID. For more information, see the Azure Docs.
- *
- * @param leaseId
- * The leaseId of the active lease on the blob.
- * @param proposedID
- * A {@code String} in any valid GUID format.
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blob_lease "Sample code for BlobAsyncRawClient.changeLease")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono changeLease(String leaseId, String proposedID) {
- return this.changeLease(leaseId, proposedID, null);
- }
-
- /**
- * ChangeLease changes the blob's lease ID. For more information, see the Azure Docs.
- *
- * @param leaseId
- * The leaseId of the active lease on the blob.
- * @param proposedID
- * A {@code String} in any valid GUID format.
- * @param modifiedAccessConditions
- * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used
- * to construct conditions related to when the blob was changed relative to the given request. The request
- * will fail if the specified condition is not satisfied.
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blob_lease "Sample code for BlobAsyncRawClient.changeLease")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono changeLease(String leaseId, String proposedID,
- ModifiedAccessConditions modifiedAccessConditions) {
- return postProcessResponse(this.azureBlobStorage.blobs().changeLeaseWithRestResponseAsync(null,
- null, leaseId, proposedID, null, null, modifiedAccessConditions, Context.NONE));
- }
-
- /**
- * Returns the sku name and account kind for the account. For more information, please see the Azure Docs.
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=account_info "Sample code for BlobAsyncRawClient.getAccountInfo")] \n
- * For more samples, please see the [Samples file](https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono getAccountInfo() {
- return postProcessResponse(
- this.azureBlobStorage.blobs().getAccountInfoWithRestResponseAsync(null, null, Context.NONE));
- }
-}
diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobClient.java
index f47c3cf6d7830..e2c6eab47a768 100644
--- a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobClient.java
+++ b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobClient.java
@@ -16,6 +16,7 @@
import com.azure.storage.blob.models.ModifiedAccessConditions;
import com.azure.storage.blob.models.ReliableDownloadOptions;
import com.azure.storage.blob.models.StorageAccountInfo;
+import com.azure.storage.blob.models.UserDelegationKey;
import reactor.core.publisher.Mono;
import java.io.IOException;
@@ -23,32 +24,34 @@
import java.io.UncheckedIOException;
import java.net.URL;
import java.time.Duration;
+import java.time.OffsetDateTime;
/**
- * Client to a blob of any type: block, append, or page. It may only be instantiated through a {@link BlobClientBuilder} or via
- * the method {@link ContainerClient#getBlobClient(String)}. This class does not hold any state about a particular
- * blob, but is instead a convenient way of sending appropriate requests to the resource on the service.
+ * Client to a blob of any type: block, append, or page. It may only be instantiated through a {@link BlobClientBuilder}
+ * or via the method {@link ContainerClient#getBlobClient(String)}. This class does not hold any state about a
+ * particular blob, but is instead a convenient way of sending appropriate requests to the resource on the service.
*
*
* This client offers the ability to download blobs. Note that uploading data is specific to each type of blob. Please
* refer to the {@link BlockBlobClient}, {@link PageBlobClient}, or {@link AppendBlobClient} for upload options. This
- * client can be converted into one of these clients easily through the methods {@link #asBlockBlobClient}, {@link #asPageBlobClient},
- * and {@link #asAppendBlobClient}.
+ * client can be converted into one of these clients easily through the methods {@link #asBlockBlobClient}, {@link
+ * #asPageBlobClient}, and {@link #asAppendBlobClient}.
*
*
- * This client contains operations on a blob. Operations on a container are available on {@link ContainerClient},
- * and operations on the service are available on {@link StorageClient}.
+ * This client contains operations on a blob. Operations on a container are available on {@link ContainerClient}, and
+ * operations on the service are available on {@link StorageClient}.
*
*
- * Please refer to the Azure Docs
- * for more information.
+ * Please refer to the Azure
+ * Docs for more information.
*/
+@SuppressWarnings({"unused", "WeakerAccess"})
public class BlobClient {
- private static final int BLOB_DEFAULT_DOWNLOAD_BLOCK_SIZE = 4 * Constants.MB;
private final BlobAsyncClient blobAsyncClient;
/**
* Package-private constructor for use by {@link BlobClientBuilder}.
+ *
* @param blobAsyncClient the async blob client
*/
BlobClient(BlobAsyncClient blobAsyncClient) {
@@ -56,45 +59,41 @@ public class BlobClient {
}
/**
- * Creates a new {@link BlockBlobClient} to this resource, maintaining configurations. Only do this for blobs
- * that are known to be block blobs.
+ * Creates a new {@link BlockBlobClient} to this resource, maintaining configurations. Only do this for blobs that
+ * are known to be block blobs.
*
- * @return
- * A {@link BlockBlobClient} to this resource.
+ * @return A {@link BlockBlobClient} to this resource.
*/
public BlockBlobClient asBlockBlobClient() {
return new BlockBlobClient(blobAsyncClient.asBlockBlobAsyncClient());
}
/**
- * Creates a new {@link AppendBlobClient} to this resource, maintaining configurations. Only do this for blobs
- * that are known to be append blobs.
+ * Creates a new {@link AppendBlobClient} to this resource, maintaining configurations. Only do this for blobs that
+ * are known to be append blobs.
*
- * @return
- * A {@link AppendBlobClient} to this resource.
+ * @return A {@link AppendBlobClient} to this resource.
*/
public AppendBlobClient asAppendBlobClient() {
return new AppendBlobClient(blobAsyncClient.asAppendBlobAsyncClient());
}
/**
- * Creates a new {@link PageBlobClient} to this resource, maintaining configurations. Only do this for blobs
- * that are known to be page blobs.
+ * Creates a new {@link PageBlobClient} to this resource, maintaining configurations. Only do this for blobs that
+ * are known to be page blobs.
*
- * @return
- * A {@link PageBlobClient} to this resource.
+ * @return A {@link PageBlobClient} to this resource.
*/
public PageBlobClient asPageBlobClient() {
return new PageBlobClient(blobAsyncClient.asPageBlobAsyncClient());
}
/**
- * Initializes a {@link ContainerClient} object pointing to the container this blob is in. This method does
- * not create a container. It simply constructs the URL to the container and offers access to methods relevant to
+ * Initializes a {@link ContainerClient} object pointing to the container this blob is in. This method does not
+ * create a container. It simply constructs the URL to the container and offers access to methods relevant to
* containers.
*
- * @return
- * A {@link ContainerClient} object pointing to the container containing the blob
+ * @return A {@link ContainerClient} object pointing to the container containing the blob
*/
public ContainerClient getContainerClient() {
return new ContainerClient(blobAsyncClient.getContainerAsyncClient());
@@ -102,6 +101,7 @@ public ContainerClient getContainerClient() {
/**
* Gets the URL of the blob represented by this client.
+ *
* @return the URL.
*/
public URL getBlobUrl() {
@@ -113,9 +113,7 @@ public URL getBlobUrl() {
*
*
* @return An InputStream
object that represents the stream to use for reading from the blob.
- *
- * @throws StorageException
- * If a storage service error occurred.
+ * @throws StorageException If a storage service error occurred.
*/
public final BlobInputStream openInputStream() {
return openInputStream(new BlobRange(0), null);
@@ -125,15 +123,11 @@ public final BlobInputStream openInputStream() {
* Opens a blob input stream to download the specified range of the blob.
*
*
- * @param range
- * {@link BlobRange}
- * @param accessConditions
- * An {@link BlobAccessConditions} object that represents the access conditions for the blob.
- *
+ * @param range {@link BlobRange}
+ * @param accessConditions An {@link BlobAccessConditions} object that represents the access conditions for the
+ * blob.
* @return An InputStream
object that represents the stream to use for reading from the blob.
- *
- * @throws StorageException
- * If a storage service error occurred.
+ * @throws StorageException If a storage service error occurred.
*/
public final BlobInputStream openInputStream(BlobRange range, BlobAccessConditions accessConditions) {
return new BlobInputStream(blobAsyncClient, range.offset(), range.count(), accessConditions);
@@ -151,10 +145,8 @@ public Response exists() {
/**
* Gets if the container this client represents exists in the cloud.
*
- * @param timeout
- * An optional timeout value beyond which a {@link RuntimeException} will be raised.
- * @return
- * true if the container exists, false if it doesn't
+ * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised.
+ * @return true if the container exists, false if it doesn't
*/
public Response exists(Duration timeout) {
Mono> response = blobAsyncClient.exists();
@@ -166,11 +158,8 @@ public Response exists(Duration timeout) {
* Copies the data at the source URL to a blob. For more information, see the
* Azure Docs
*
- * @param sourceURL
- * The source URL to copy from. URLs outside of Azure may only be copied to block blobs.
- *
- * @return
- * The copy ID for the long running operation.
+ * @param sourceURL The source URL to copy from. URLs outside of Azure may only be copied to block blobs.
+ * @return The copy ID for the long running operation.
*/
public Response startCopyFromURL(URL sourceURL) {
return this.startCopyFromURL(sourceURL, null, null, null, null);
@@ -180,26 +169,19 @@ public Response startCopyFromURL(URL sourceURL) {
* Copies the data at the source URL to a blob. For more information, see the
* Azure Docs
*
- * @param sourceURL
- * The source URL to copy from. URLs outside of Azure may only be copied to block blobs.
- * @param metadata
- * {@link Metadata}
- * @param sourceModifiedAccessConditions
- * {@link ModifiedAccessConditions} against the source. Standard HTTP Access conditions related to the
- * modification of data. ETag and LastModifiedTime are used to construct conditions related to when the blob
- * was changed relative to the given request. The request will fail if the specified condition is not
- * satisfied.
- * @param destAccessConditions
- * {@link BlobAccessConditions} against the destination.
- * @param timeout
- * An optional timeout value beyond which a {@link RuntimeException} will be raised.
- *
- * @return
- * The copy ID for the long running operation.
+ * @param sourceURL The source URL to copy from. URLs outside of Azure may only be copied to block blobs.
+ * @param metadata {@link Metadata}
+ * @param sourceModifiedAccessConditions {@link ModifiedAccessConditions} against the source. Standard HTTP Access
+ * conditions related to the modification of data. ETag and LastModifiedTime are used to construct conditions
+ * related to when the blob was changed relative to the given request. The request will fail if the specified
+ * condition is not satisfied.
+ * @param destAccessConditions {@link BlobAccessConditions} against the destination.
+ * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised.
+ * @return The copy ID for the long running operation.
*/
public Response startCopyFromURL(URL sourceURL, Metadata metadata,
- ModifiedAccessConditions sourceModifiedAccessConditions, BlobAccessConditions destAccessConditions,
- Duration timeout) {
+ ModifiedAccessConditions sourceModifiedAccessConditions, BlobAccessConditions destAccessConditions,
+ Duration timeout) {
Mono> response = blobAsyncClient
.startCopyFromURL(sourceURL, metadata, sourceModifiedAccessConditions, destAccessConditions);
@@ -209,9 +191,8 @@ public Response startCopyFromURL(URL sourceURL, Metadata metadata,
/**
* Stops a pending copy that was previously started and leaves a destination blob with 0 length and metadata.
*
- * @param copyId
- * The id of the copy operation to abort. Returned as the {@code copyId} field on the {@link
- * BlobStartCopyFromURLHeaders} object.
+ * @param copyId The id of the copy operation to abort. Returned as the {@code copyId} field on the {@link
+ * BlobStartCopyFromURLHeaders} object.
* @return A response containing status code and HTTP headers.
*/
public VoidResponse abortCopyFromURL(String copyId) {
@@ -221,14 +202,11 @@ public VoidResponse abortCopyFromURL(String copyId) {
/**
* Stops a pending copy that was previously started and leaves a destination blob with 0 length and metadata.
*
- * @param copyId
- * The id of the copy operation to abort. Returned as the {@code copyId} field on the {@link
- * BlobStartCopyFromURLHeaders} object.
- * @param leaseAccessConditions
- * By setting lease access conditions, requests will fail if the provided lease does not match the active
- * lease on the blob.
- * @param timeout
- * An optional timeout value beyond which a {@link RuntimeException} will be raised.
+ * @param copyId The id of the copy operation to abort. Returned as the {@code copyId} field on the {@link
+ * BlobStartCopyFromURLHeaders} object.
+ * @param leaseAccessConditions By setting lease access conditions, requests will fail if the provided lease does
+ * not match the active lease on the blob.
+ * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised.
* @return A response containing status code and HTTP headers.
*/
public VoidResponse abortCopyFromURL(String copyId, LeaseAccessConditions leaseAccessConditions, Duration timeout) {
@@ -241,11 +219,8 @@ public VoidResponse abortCopyFromURL(String copyId, LeaseAccessConditions leaseA
/**
* Copies the data at the source URL to a blob and waits for the copy to complete before returning a response.
*
- * @param copySource
- * The source URL to copy from.
- *
- * @return
- * The copy ID for the long running operation.
+ * @param copySource The source URL to copy from.
+ * @return The copy ID for the long running operation.
*/
public Response copyFromURL(URL copySource) {
return this.copyFromURL(copySource, null, null, null, null);
@@ -254,26 +229,19 @@ public Response copyFromURL(URL copySource) {
/**
* Copies the data at the source URL to a blob and waits for the copy to complete before returning a response.
*
- * @param copySource
- * The source URL to copy from. URLs outside of Azure may only be copied to block blobs.
- * @param metadata
- * {@link Metadata}
- * @param sourceModifiedAccessConditions
- * {@link ModifiedAccessConditions} against the source. Standard HTTP Access conditions related to the
- * modification of data. ETag and LastModifiedTime are used to construct conditions related to when the blob
- * was changed relative to the given request. The request will fail if the specified condition is not
- * satisfied.
- * @param destAccessConditions
- * {@link BlobAccessConditions} against the destination.
- * @param timeout
- * An optional timeout value beyond which a {@link RuntimeException} will be raised.
- *
- * @return
- * The copy ID for the long running operation.
+ * @param copySource The source URL to copy from. URLs outside of Azure may only be copied to block blobs.
+ * @param metadata {@link Metadata}
+ * @param sourceModifiedAccessConditions {@link ModifiedAccessConditions} against the source. Standard HTTP Access
+ * conditions related to the modification of data. ETag and LastModifiedTime are used to construct conditions
+ * related to when the blob was changed relative to the given request. The request will fail if the specified
+ * condition is not satisfied.
+ * @param destAccessConditions {@link BlobAccessConditions} against the destination.
+ * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised.
+ * @return The copy ID for the long running operation.
*/
public Response copyFromURL(URL copySource, Metadata metadata,
- ModifiedAccessConditions sourceModifiedAccessConditions, BlobAccessConditions destAccessConditions,
- Duration timeout) {
+ ModifiedAccessConditions sourceModifiedAccessConditions, BlobAccessConditions destAccessConditions,
+ Duration timeout) {
Mono> response = blobAsyncClient
.copyFromURL(copySource, metadata, sourceModifiedAccessConditions, destAccessConditions);
@@ -284,8 +252,7 @@ public Response copyFromURL(URL copySource, Metadata metadata,
* Downloads the entire blob into an output stream. Uploading data must be done from the {@link BlockBlobClient},
* {@link PageBlobClient}, or {@link AppendBlobClient}.
*
- * @param stream
- * A non-null {@link OutputStream} instance where the downloaded data will be written.
+ * @param stream A non-null {@link OutputStream} instance where the downloaded data will be written.
* @return A response containing status code and HTTP headers.
* @throws UncheckedIOException If an I/O error occurs.
*/
@@ -294,23 +261,17 @@ public VoidResponse download(OutputStream stream) {
}
/**
- * Downloads a range of bytes from a blob into an output stream. Uploading data must be done from the {@link BlockBlobClient},
- * {@link PageBlobClient}, or {@link AppendBlobClient}.
+ * Downloads a range of bytes from a blob into an output stream. Uploading data must be done from the {@link
+ * BlockBlobClient}, {@link PageBlobClient}, or {@link AppendBlobClient}.
*
- * @param stream
- * A non-null {@link OutputStream} instance where the downloaded data will be written.
+ * @param stream A non-null {@link OutputStream} instance where the downloaded data will be written.
* @param options {@link ReliableDownloadOptions}
- * @param range
- * {@link BlobRange}
- * @param accessConditions
- * {@link BlobAccessConditions}
- * @param rangeGetContentMD5
- * Whether the contentMD5 for the specified blob range should be returned.
- * @param timeout
- * An optional timeout value beyond which a {@link RuntimeException} will be raised.
+ * @param range {@link BlobRange}
+ * @param accessConditions {@link BlobAccessConditions}
+ * @param rangeGetContentMD5 Whether the contentMD5 for the specified blob range should be returned.
+ * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised.
* @return A response containing status code and HTTP headers.
* @throws UncheckedIOException If an I/O error occurs.
- *
*/
public VoidResponse download(OutputStream stream, ReliableDownloadOptions options, BlobRange range,
BlobAccessConditions accessConditions, boolean rangeGetContentMD5, Duration timeout) {
@@ -332,37 +293,32 @@ public VoidResponse download(OutputStream stream, ReliableDownloadOptions option
/**
* Downloads the entire blob into a file specified by the path. The file will be created if it doesn't exist.
- * Uploading data must be done from the {@link BlockBlobClient}, {@link PageBlobClient}, or {@link AppendBlobClient}.
+ * Uploading data must be done from the {@link BlockBlobClient}, {@link PageBlobClient}, or {@link
+ * AppendBlobClient}.
*
- * @param filePath
- * A non-null {@link OutputStream} instance where the downloaded data will be written.
+ * @param filePath A non-null {@link OutputStream} instance where the downloaded data will be written.
* @throws IOException If an I/O error occurs
*/
public void downloadToFile(String filePath) throws IOException {
- this.downloadToFile(filePath, null, null, BLOB_DEFAULT_DOWNLOAD_BLOCK_SIZE, null, false, null);
+ blobAsyncClient.downloadToFile(filePath);
}
/**
* Downloads a range of bytes blob into a file specified by the path. The file will be created if it doesn't exist.
- * Uploading data must be done from the {@link BlockBlobClient}, {@link PageBlobClient}, or {@link AppendBlobClient}.
+ * Uploading data must be done from the {@link BlockBlobClient}, {@link PageBlobClient}, or {@link
+ * AppendBlobClient}.
*
- * @param filePath
- * A non-null {@link OutputStream} instance where the downloaded data will be written.
+ * @param filePath A non-null {@link OutputStream} instance where the downloaded data will be written.
* @param options {@link ReliableDownloadOptions}
- * @param range
- * {@link BlobRange}
- * @param blockSize
- * the size of a chunk to download at a time, in bytes
- * @param accessConditions
- * {@link BlobAccessConditions}
- * @param rangeGetContentMD5
- * Whether the contentMD5 for the specified blob range should be returned.
- * @param timeout
- * An optional timeout value beyond which a {@link RuntimeException} will be raised.
+ * @param range {@link BlobRange}
+ * @param blockSize the size of a chunk to download at a time, in bytes
+ * @param accessConditions {@link BlobAccessConditions}
+ * @param rangeGetContentMD5 Whether the contentMD5 for the specified blob range should be returned.
+ * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised.
* @throws IOException If an I/O error occurs
*/
public void downloadToFile(String filePath, ReliableDownloadOptions options, BlobRange range, Integer blockSize,
- BlobAccessConditions accessConditions, boolean rangeGetContentMD5, Duration timeout) throws IOException {
+ BlobAccessConditions accessConditions, boolean rangeGetContentMD5, Duration timeout) throws IOException {
Mono download = blobAsyncClient.downloadToFile(filePath, range, blockSize, accessConditions, rangeGetContentMD5, options);
try {
@@ -384,19 +340,15 @@ public VoidResponse delete() {
/**
* Deletes the specified blob or snapshot. Note that deleting a blob also deletes all its snapshots.
*
- * @param deleteBlobSnapshotOptions
- * Specifies the behavior for deleting the snapshots on this blob. {@code Include} will delete the base blob
- * and all snapshots. {@code Only} will delete only the snapshots. If a snapshot is being deleted, you must
- * pass null.
- * @param accessConditions
- * {@link BlobAccessConditions}
- * @param timeout
- * An optional timeout value beyond which a {@link RuntimeException} will be raised.
- *
+ * @param deleteBlobSnapshotOptions Specifies the behavior for deleting the snapshots on this blob. {@code Include}
+ * will delete the base blob and all snapshots. {@code Only} will delete only the snapshots. If a snapshot is being
+ * deleted, you must pass null.
+ * @param accessConditions {@link BlobAccessConditions}
+ * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised.
* @return A response containing status code and HTTP headers.
*/
public VoidResponse delete(DeleteSnapshotsOptionType deleteBlobSnapshotOptions,
- BlobAccessConditions accessConditions, Duration timeout) {
+ BlobAccessConditions accessConditions, Duration timeout) {
Mono response = blobAsyncClient
.delete(deleteBlobSnapshotOptions, accessConditions);
@@ -406,8 +358,7 @@ public VoidResponse delete(DeleteSnapshotsOptionType deleteBlobSnapshotOptions,
/**
* Returns the blob's metadata and properties.
*
- * @return
- * The blob properties and metadata.
+ * @return The blob properties and metadata.
*/
public Response getProperties() {
return this.getProperties(null, null);
@@ -416,13 +367,9 @@ public Response getProperties() {
/**
* Returns the blob's metadata and properties.
*
- * @param accessConditions
- * {@link BlobAccessConditions}
- * @param timeout
- * An optional timeout value beyond which a {@link RuntimeException} will be raised.
- *
- * @return
- * The blob properties and metadata.
+ * @param accessConditions {@link BlobAccessConditions}
+ * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised.
+ * @return The blob properties and metadata.
*/
public Response getProperties(BlobAccessConditions accessConditions, Duration timeout) {
Mono> response = blobAsyncClient
@@ -432,13 +379,12 @@ public Response getProperties(BlobAccessConditions accessConditi
}
/**
- * Changes a blob's HTTP header properties. if only one HTTP header is updated, the
- * others will all be erased. In order to preserve existing values, they must be
- * passed alongside the header being changed. For more information, see the
+ * Changes a blob's HTTP header properties. if only one HTTP header is updated, the others will all be erased. In
+ * order to preserve existing values, they must be passed alongside the header being changed. For more information,
+ * see the
* Azure Docs.
*
- * @param headers
- * {@link BlobHTTPHeaders}
+ * @param headers {@link BlobHTTPHeaders}
* @return A response containing status code and HTTP headers.
*/
public VoidResponse setHTTPHeaders(BlobHTTPHeaders headers) {
@@ -446,21 +392,18 @@ public VoidResponse setHTTPHeaders(BlobHTTPHeaders headers) {
}
/**
- * Changes a blob's HTTP header properties. if only one HTTP header is updated, the
- * others will all be erased. In order to preserve existing values, they must be
- * passed alongside the header being changed. For more information, see the
+ * Changes a blob's HTTP header properties. if only one HTTP header is updated, the others will all be erased. In
+ * order to preserve existing values, they must be passed alongside the header being changed. For more information,
+ * see the
* Azure Docs.
*
- * @param headers
- * {@link BlobHTTPHeaders}
- * @param accessConditions
- * {@link BlobAccessConditions}
- * @param timeout
- * An optional timeout value beyond which a {@link RuntimeException} will be raised.
+ * @param headers {@link BlobHTTPHeaders}
+ * @param accessConditions {@link BlobAccessConditions}
+ * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised.
* @return A response containing status code and HTTP headers.
*/
public VoidResponse setHTTPHeaders(BlobHTTPHeaders headers, BlobAccessConditions accessConditions,
- Duration timeout) {
+ Duration timeout) {
Mono response = blobAsyncClient
.setHTTPHeaders(headers, accessConditions);
@@ -468,12 +411,11 @@ public VoidResponse setHTTPHeaders(BlobHTTPHeaders headers, BlobAccessConditions
}
/**
- * Changes a blob's metadata. The specified metadata in this method will replace existing
- * metadata. If old values must be preserved, they must be downloaded and included in the
- * call to this method. For more information, see the Azure Docs.
+ * Changes a blob's metadata. The specified metadata in this method will replace existing metadata. If old values
+ * must be preserved, they must be downloaded and included in the call to this method. For more information, see the
+ * Azure Docs.
*
- * @param metadata
- * {@link Metadata}
+ * @param metadata {@link Metadata}
* @return A response containing status code and HTTP headers.
*/
public VoidResponse setMetadata(Metadata metadata) {
@@ -481,16 +423,13 @@ public VoidResponse setMetadata(Metadata metadata) {
}
/**
- * Changes a blob's metadata. The specified metadata in this method will replace existing
- * metadata. If old values must be preserved, they must be downloaded and included in the
- * call to this method. For more information, see the Azure Docs.
+ * Changes a blob's metadata. The specified metadata in this method will replace existing metadata. If old values
+ * must be preserved, they must be downloaded and included in the call to this method. For more information, see the
+ * Azure Docs.
*
- * @param metadata
- * {@link Metadata}
- * @param accessConditions
- * {@link BlobAccessConditions}
- * @param timeout
- * An optional timeout value beyond which a {@link RuntimeException} will be raised.
+ * @param metadata {@link Metadata}
+ * @param accessConditions {@link BlobAccessConditions}
+ * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised.
* @return A response containing status code and HTTP headers.
*/
public VoidResponse setMetadata(Metadata metadata, BlobAccessConditions accessConditions, Duration timeout) {
@@ -503,8 +442,7 @@ public VoidResponse setMetadata(Metadata metadata, BlobAccessConditions accessCo
/**
* Creates a read-only snapshot of a blob.
*
- * @return
- * The ID of the new snapshot.
+ * @return The ID of the new snapshot.
*/
public Response createSnapshot() {
return this.createSnapshot(null, null, null);
@@ -513,15 +451,10 @@ public Response createSnapshot() {
/**
* Creates a read-only snapshot of a blob.
*
- * @param metadata
- * {@link Metadata}
- * @param accessConditions
- * {@link BlobAccessConditions}
- * @param timeout
- * An optional timeout value beyond which a {@link RuntimeException} will be raised.
- *
- * @return
- * The ID of the new snapshot.
+ * @param metadata {@link Metadata}
+ * @param accessConditions {@link BlobAccessConditions}
+ * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised.
+ * @return The ID of the new snapshot.
*/
public Response createSnapshot(Metadata metadata, BlobAccessConditions accessConditions, Duration timeout) {
Mono> response = blobAsyncClient
@@ -533,10 +466,10 @@ public Response createSnapshot(Metadata metadata, BlobAccessConditions a
/**
* Sets the tier on a blob. The operation is allowed on a page blob in a premium storage account or a block blob in
* a blob storage or GPV2 account. A premium page blob's tier determines the allowed size, IOPS, and bandwidth of
- * the blob. A block blob's tier determines the Hot/Cool/Archive storage type. This does not update the blob's etag.
+ * the blob. A block blob's tier determines the Hot/Cool/Archive storage type. This does not update the blob's
+ * etag.
*
- * @param tier
- * The new tier for the blob.
+ * @param tier The new tier for the blob.
* @return A response containing status code and HTTP headers.
*/
public VoidResponse setTier(AccessTier tier) {
@@ -546,15 +479,13 @@ public VoidResponse setTier(AccessTier tier) {
/**
* Sets the tier on a blob. The operation is allowed on a page blob in a premium storage account or a block blob in
* a blob storage or GPV2 account. A premium page blob's tier determines the allowed size, IOPS, and bandwidth of
- * the blob. A block blob's tier determines the Hot/Cool/Archive storage type. This does not update the blob's etag.
- *
- * @param tier
- * The new tier for the blob.
- * @param leaseAccessConditions
- * By setting lease access conditions, requests will fail if the provided lease does not match the active
- * lease on the blob.
- * @param timeout
- * An optional timeout value beyond which a {@link RuntimeException} will be raised.
+ * the blob. A block blob's tier determines the Hot/Cool/Archive storage type. This does not update the blob's
+ * etag.
+ *
+ * @param tier The new tier for the blob.
+ * @param leaseAccessConditions By setting lease access conditions, requests will fail if the provided lease does
+ * not match the active lease on the blob.
+ * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised.
* @return A response containing status code and HTTP headers.
*/
public VoidResponse setTier(AccessTier tier, LeaseAccessConditions leaseAccessConditions, Duration timeout) {
@@ -576,8 +507,7 @@ public VoidResponse undelete() {
/**
* Undelete restores the content and metadata of a soft-deleted blob and/or any associated soft-deleted snapshots.
*
- * @param timeout
- * An optional timeout value beyond which a {@link RuntimeException} will be raised.
+ * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised.
* @return A response containing status code and HTTP headers.
*/
public VoidResponse undelete(Duration timeout) {
@@ -591,14 +521,10 @@ public VoidResponse undelete(Duration timeout) {
* Acquires a lease on the blob for write and delete operations. The lease duration must be between 15 to 60
* seconds, or infinite (-1).
*
- * @param proposedId
- * A {@code String} in any valid GUID format. May be null.
- * @param duration
- * The duration of the lease, in seconds, or negative one (-1) for a lease that
- * never expires. A non-infinite lease can be between 15 and 60 seconds.
- *
- * @return
- * The lease ID.
+ * @param proposedId A {@code String} in any valid GUID format. May be null.
+ * @param duration The duration of the lease, in seconds, or negative one (-1) for a lease that never expires. A
+ * non-infinite lease can be between 15 and 60 seconds.
+ * @return The lease ID.
*/
public Response acquireLease(String proposedId, int duration) {
return this.acquireLease(proposedId, duration, null, null);
@@ -608,23 +534,17 @@ public Response acquireLease(String proposedId, int duration) {
* Acquires a lease on the blob for write and delete operations. The lease duration must be between 15 to 60
* seconds, or infinite (-1).
*
- * @param proposedID
- * A {@code String} in any valid GUID format. May be null.
- * @param duration
- * The duration of the lease, in seconds, or negative one (-1) for a lease that
- * never expires. A non-infinite lease can be between 15 and 60 seconds.
- * @param modifiedAccessConditions
- * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used
- * to construct conditions related to when the blob was changed relative to the given request. The request
- * will fail if the specified condition is not satisfied.
- * @param timeout
- * An optional timeout value beyond which a {@link RuntimeException} will be raised.
- *
- * @return
- * The lease ID.
+ * @param proposedID A {@code String} in any valid GUID format. May be null.
+ * @param duration The duration of the lease, in seconds, or negative one (-1) for a lease that never expires. A
+ * non-infinite lease can be between 15 and 60 seconds.
+ * @param modifiedAccessConditions Standard HTTP Access conditions related to the modification of data. ETag and
+ * LastModifiedTime are used to construct conditions related to when the blob was changed relative to the given
+ * request. The request will fail if the specified condition is not satisfied.
+ * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised.
+ * @return The lease ID.
*/
public Response acquireLease(String proposedID, int duration,
- ModifiedAccessConditions modifiedAccessConditions, Duration timeout) {
+ ModifiedAccessConditions modifiedAccessConditions, Duration timeout) {
Mono> response = blobAsyncClient
.acquireLease(proposedID, duration, modifiedAccessConditions);
@@ -634,11 +554,8 @@ public Response acquireLease(String proposedID, int duration,
/**
* Renews the blob's previously-acquired lease.
*
- * @param leaseID
- * The leaseId of the active lease on the blob.
- *
- * @return
- * The renewed lease ID.
+ * @param leaseID The leaseId of the active lease on the blob.
+ * @return The renewed lease ID.
*/
public Response renewLease(String leaseID) {
return this.renewLease(leaseID, null, null);
@@ -647,20 +564,15 @@ public Response renewLease(String leaseID) {
/**
* Renews the blob's previously-acquired lease.
*
- * @param leaseID
- * The leaseId of the active lease on the blob.
- * @param modifiedAccessConditions
- * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used
- * to construct conditions related to when the blob was changed relative to the given request. The request
- * will fail if the specified condition is not satisfied.
- * @param timeout
- * An optional timeout value beyond which a {@link RuntimeException} will be raised.
- *
- * @return
- * The renewed lease ID.
+ * @param leaseID The leaseId of the active lease on the blob.
+ * @param modifiedAccessConditions Standard HTTP Access conditions related to the modification of data. ETag and
+ * LastModifiedTime are used to construct conditions related to when the blob was changed relative to the given
+ * request. The request will fail if the specified condition is not satisfied.
+ * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised.
+ * @return The renewed lease ID.
*/
public Response renewLease(String leaseID, ModifiedAccessConditions modifiedAccessConditions,
- Duration timeout) {
+ Duration timeout) {
Mono> response = blobAsyncClient
.renewLease(leaseID, modifiedAccessConditions);
@@ -670,8 +582,7 @@ public Response renewLease(String leaseID, ModifiedAccessConditions modi
/**
* Releases the blob's previously-acquired lease.
*
- * @param leaseID
- * The leaseId of the active lease on the blob.
+ * @param leaseID The leaseId of the active lease on the blob.
* @return A response containing status code and HTTP headers.
*/
public VoidResponse releaseLease(String leaseID) {
@@ -681,18 +592,15 @@ public VoidResponse releaseLease(String leaseID) {
/**
* Releases the blob's previously-acquired lease.
*
- * @param leaseID
- * The leaseId of the active lease on the blob.
- * @param modifiedAccessConditions
- * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used
- * to construct conditions related to when the blob was changed relative to the given request. The request
- * will fail if the specified condition is not satisfied.
- * @param timeout
- * An optional timeout value beyond which a {@link RuntimeException} will be raised.
+ * @param leaseID The leaseId of the active lease on the blob.
+ * @param modifiedAccessConditions Standard HTTP Access conditions related to the modification of data. ETag and
+ * LastModifiedTime are used to construct conditions related to when the blob was changed relative to the given
+ * request. The request will fail if the specified condition is not satisfied.
+ * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised.
* @return A response containing status code and HTTP headers.
*/
public VoidResponse releaseLease(String leaseID,
- ModifiedAccessConditions modifiedAccessConditions, Duration timeout) {
+ ModifiedAccessConditions modifiedAccessConditions, Duration timeout) {
Mono response = blobAsyncClient
.releaseLease(leaseID, modifiedAccessConditions);
@@ -703,8 +611,7 @@ public VoidResponse releaseLease(String leaseID,
* BreakLease breaks the blob's previously-acquired lease (if it exists). Pass the LeaseBreakDefault (-1) constant
* to break a fixed-duration lease when it expires or an infinite lease immediately.
*
- * @return
- * The remaining time in the broken lease in seconds.
+ * @return The remaining time in the broken lease in seconds.
*/
public Response breakLease() {
return this.breakLease(null, null, null);
@@ -714,24 +621,19 @@ public Response breakLease() {
* BreakLease breaks the blob's previously-acquired lease (if it exists). Pass the LeaseBreakDefault (-1) constant
* to break a fixed-duration lease when it expires or an infinite lease immediately.
*
- * @param breakPeriodInSeconds
- * An optional {@code Integer} representing the proposed duration of seconds that the lease should continue
- * before it is broken, between 0 and 60 seconds. This break period is only used if it is shorter than the
- * time remaining on the lease. If longer, the time remaining on the lease is used. A new lease will not be
- * available before the break period has expired, but the lease may be held for longer than the break
- * period.
- * @param modifiedAccessConditions
- * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used
- * to construct conditions related to when the blob was changed relative to the given request. The request
- * will fail if the specified condition is not satisfied.
- * @param timeout
- * An optional timeout value beyond which a {@link RuntimeException} will be raised.
- *
- * @return
- * The remaining time in the broken lease in seconds.
+ * @param breakPeriodInSeconds An optional {@code Integer} representing the proposed duration of seconds that the
+ * lease should continue before it is broken, between 0 and 60 seconds. This break period is only used if it is
+ * shorter than the time remaining on the lease. If longer, the time remaining on the lease is used. A new lease
+ * will not be available before the break period has expired, but the lease may be held for longer than the break
+ * period.
+ * @param modifiedAccessConditions Standard HTTP Access conditions related to the modification of data. ETag and
+ * LastModifiedTime are used to construct conditions related to when the blob was changed relative to the given
+ * request. The request will fail if the specified condition is not satisfied.
+ * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised.
+ * @return The remaining time in the broken lease in seconds.
*/
public Response breakLease(Integer breakPeriodInSeconds,
- ModifiedAccessConditions modifiedAccessConditions, Duration timeout) {
+ ModifiedAccessConditions modifiedAccessConditions, Duration timeout) {
Mono> response = blobAsyncClient
.breakLease(breakPeriodInSeconds, modifiedAccessConditions);
@@ -741,36 +643,28 @@ public Response breakLease(Integer breakPeriodInSeconds,
/**
* ChangeLease changes the blob's lease ID.
*
- * @param leaseId
- * The leaseId of the active lease on the blob.
- * @param proposedID
- * A {@code String} in any valid GUID format.
- *
- * @return
- * The new lease ID.
+ * @param leaseId The leaseId of the active lease on the blob.
+ * @param proposedID A {@code String} in any valid GUID format.
+ * @return The new lease ID.
*/
public Response changeLease(String leaseId, String proposedID) {
return this.changeLease(leaseId, proposedID, null, null);
}
/**
- * ChangeLease changes the blob's lease ID. For more information, see the Azure Docs.
- *
- * @param leaseId
- * The leaseId of the active lease on the blob.
- * @param proposedID
- * A {@code String} in any valid GUID format.
- * @param modifiedAccessConditions
- * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used
- * to construct conditions related to when the blob was changed relative to the given request. The request
- * will fail if the specified condition is not satisfied.
- * @param timeout
- * An optional timeout value beyond which a {@link RuntimeException} will be raised.
+ * ChangeLease changes the blob's lease ID. For more information, see the Azure
+ * Docs.
*
+ * @param leaseId The leaseId of the active lease on the blob.
+ * @param proposedID A {@code String} in any valid GUID format.
+ * @param modifiedAccessConditions Standard HTTP Access conditions related to the modification of data. ETag and
+ * LastModifiedTime are used to construct conditions related to when the blob was changed relative to the given
+ * request. The request will fail if the specified condition is not satisfied.
+ * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised.
* @return The new lease ID.
*/
public Response changeLease(String leaseId, String proposedID,
- ModifiedAccessConditions modifiedAccessConditions, Duration timeout) {
+ ModifiedAccessConditions modifiedAccessConditions, Duration timeout) {
Mono> response = blobAsyncClient
.changeLease(leaseId, proposedID, modifiedAccessConditions);
@@ -778,7 +672,8 @@ public Response changeLease(String leaseId, String proposedID,
}
/**
- * Returns the sku name and account kind for the account. For more information, please see the Azure Docs.
+ * Returns the sku name and account kind for the account. For more information, please see the Azure Docs.
*
* @return The sku name and account kind.
*/
@@ -787,11 +682,10 @@ public Response getAccountInfo() {
}
/**
- * Returns the sku name and account kind for the account. For more information, please see the Azure Docs.
- *
- * @param timeout
- * An optional timeout value beyond which a {@link RuntimeException} will be raised.
+ * Returns the sku name and account kind for the account. For more information, please see the Azure Docs.
*
+ * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised.
* @return The sku name and account kind.
*/
public Response getAccountInfo(Duration timeout) {
@@ -800,4 +694,146 @@ public Response getAccountInfo(Duration timeout) {
return Utility.blockWithOptionalTimeout(response, timeout);
}
+
+ /**
+ * Generates a user delegation SAS token with the specified parameters
+ *
+ * @param userDelegationKey The {@code UserDelegationKey} user delegation key for the SAS
+ * @param accountName The {@code String} account name for the SAS
+ * @param permissions The {@code ContainerSASPermissions} permission for the SAS
+ * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS
+ * @return A string that represents the SAS token
+ */
+ public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, String accountName,
+ BlobSASPermission permissions, OffsetDateTime expiryTime) {
+ return this.blobAsyncClient.generateUserDelegationSAS(userDelegationKey, accountName, permissions, expiryTime);
+ }
+
+ /**
+ * Generates a user delegation SAS token with the specified parameters
+ *
+ * @param userDelegationKey The {@code UserDelegationKey} user delegation key for the SAS
+ * @param accountName The {@code String} account name for the SAS
+ * @param permissions The {@code ContainerSASPermissions} permission for the SAS
+ * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS
+ * @param startTime An optional {@code OffsetDateTime} start time for the SAS
+ * @param version An optional {@code String} version for the SAS
+ * @param sasProtocol An optional {@code SASProtocol} protocol for the SAS
+ * @param ipRange An optional {@code IPRange} ip address range for the SAS
+ * @return A string that represents the SAS token
+ */
+ public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, String accountName,
+ BlobSASPermission permissions, OffsetDateTime expiryTime, OffsetDateTime startTime, String version,
+ SASProtocol sasProtocol, IPRange ipRange) {
+ return this.blobAsyncClient.generateUserDelegationSAS(userDelegationKey, accountName, permissions, expiryTime,
+ startTime, version, sasProtocol, ipRange);
+ }
+
+ /**
+ * Generates a user delegation SAS token with the specified parameters
+ *
+ * @param userDelegationKey The {@code UserDelegationKey} user delegation key for the SAS
+ * @param accountName The {@code String} account name for the SAS
+ * @param permissions The {@code ContainerSASPermissions} permission for the SAS
+ * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS
+ * @param startTime An optional {@code OffsetDateTime} start time for the SAS
+ * @param version An optional {@code String} version for the SAS
+ * @param sasProtocol An optional {@code SASProtocol} protocol for the SAS
+ * @param ipRange An optional {@code IPRange} ip address range for the SAS
+ * @param cacheControl An optional {@code String} cache-control header for the SAS.
+ * @param contentDisposition An optional {@code String} content-disposition header for the SAS.
+ * @param contentEncoding An optional {@code String} content-encoding header for the SAS.
+ * @param contentLanguage An optional {@code String} content-language header for the SAS.
+ * @param contentType An optional {@code String} content-type header for the SAS.
+ * @return A string that represents the SAS token
+ */
+ public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, String accountName,
+ BlobSASPermission permissions, OffsetDateTime expiryTime, OffsetDateTime startTime, String version,
+ SASProtocol sasProtocol, IPRange ipRange, String cacheControl, String contentDisposition,
+ String contentEncoding, String contentLanguage, String contentType) {
+ return this.blobAsyncClient.generateUserDelegationSAS(userDelegationKey, accountName, permissions, expiryTime,
+ startTime, version, sasProtocol, ipRange, cacheControl, contentDisposition, contentEncoding,
+ contentLanguage, contentType);
+ }
+
+ /**
+ * Generates a SAS token with the specified parameters
+ *
+ * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS
+ * @param permissions The {@code ContainerSASPermissions} permission for the SAS
+ * @return A string that represents the SAS token
+ */
+ public String generateSAS(OffsetDateTime expiryTime, BlobSASPermission permissions) {
+ return this.blobAsyncClient.generateSAS(permissions, expiryTime);
+ }
+
+ /**
+ * Generates a SAS token with the specified parameters
+ *
+ * @param identifier The {@code String} name of the access policy on the container this SAS references if any
+ * @return A string that represents the SAS token
+ */
+ public String generateSAS(String identifier) {
+ return this.blobAsyncClient.generateSAS(identifier);
+ }
+
+ /**
+ * Generates a SAS token with the specified parameters
+ *
+ * @param identifier The {@code String} name of the access policy on the container this SAS references if any
+ * @param permissions The {@code ContainerSASPermissions} permission for the SAS
+ * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS
+ * @param startTime An optional {@code OffsetDateTime} start time for the SAS
+ * @param version An optional {@code String} version for the SAS
+ * @param sasProtocol An optional {@code SASProtocol} protocol for the SAS
+ * @param ipRange An optional {@code IPRange} ip address range for the SAS
+ * @return A string that represents the SAS token
+ */
+ public String generateSAS(String identifier, BlobSASPermission permissions, OffsetDateTime expiryTime,
+ OffsetDateTime startTime, String version, SASProtocol sasProtocol, IPRange ipRange) {
+ return this.blobAsyncClient.generateSAS(identifier, permissions, expiryTime, startTime, version, sasProtocol,
+ ipRange);
+ }
+
+ /**
+ * Generates a SAS token with the specified parameters
+ *
+ * @param identifier The {@code String} name of the access policy on the container this SAS references if any
+ * @param permissions The {@code ContainerSASPermissions} permission for the SAS
+ * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS
+ * @param startTime An optional {@code OffsetDateTime} start time for the SAS
+ * @param version An optional {@code String} version for the SAS
+ * @param sasProtocol An optional {@code SASProtocol} protocol for the SAS
+ * @param ipRange An optional {@code IPRange} ip address range for the SAS
+ * @param cacheControl An optional {@code String} cache-control header for the SAS.
+ * @param contentDisposition An optional {@code String} content-disposition header for the SAS.
+ * @param contentEncoding An optional {@code String} content-encoding header for the SAS.
+ * @param contentLanguage An optional {@code String} content-language header for the SAS.
+ * @param contentType An optional {@code String} content-type header for the SAS.
+ * @return A string that represents the SAS token
+ */
+ public String generateSAS(String identifier, BlobSASPermission permissions, OffsetDateTime expiryTime,
+ OffsetDateTime startTime, String version, SASProtocol sasProtocol, IPRange ipRange, String cacheControl,
+ String contentDisposition, String contentEncoding, String contentLanguage, String contentType) {
+ return this.blobAsyncClient.generateSAS(identifier, permissions, expiryTime, startTime, version, sasProtocol,
+ ipRange, cacheControl, contentDisposition, contentEncoding, contentLanguage, contentType);
+ }
+
+ /**
+ * Gets the snapshotId for a blob resource
+ *
+ * @return A string that represents the snapshotId of the snapshot blob
+ */
+ public String getSnapshotId() {
+ return this.blobAsyncClient.getSnapshotId();
+ }
+
+ /**
+ * Determines if a blob is a snapshot
+ *
+ * @return A boolean that indicates if a blob is a snapshot
+ */
+ public boolean isSnapshot() {
+ return this.blobAsyncClient.isSnapshot();
+ }
}
diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobClientBuilder.java b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobClientBuilder.java
index 2238af18e48e9..b0e3c98d8904a 100644
--- a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobClientBuilder.java
+++ b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobClientBuilder.java
@@ -17,13 +17,17 @@
import com.azure.core.util.configuration.Configuration;
import com.azure.core.util.configuration.ConfigurationManager;
import com.azure.storage.blob.implementation.AzureBlobStorageBuilder;
+import com.azure.storage.blob.models.PageRange;
import com.azure.storage.common.credentials.SASTokenCredential;
import com.azure.storage.common.credentials.SharedKeyCredential;
import com.azure.storage.common.policy.RequestRetryOptions;
import com.azure.storage.common.policy.RequestRetryPolicy;
import com.azure.storage.common.policy.SASTokenCredentialPolicy;
import com.azure.storage.common.policy.SharedKeyCredentialPolicy;
+import reactor.core.publisher.Flux;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
@@ -34,8 +38,7 @@
import java.util.Objects;
/**
- * Fluent BlobClientBuilder for instantiating a {@link BlobClient} or {@link BlobAsyncClient}
- * using {@link BlobClientBuilder#buildClient()} or {@link BlobClientBuilder#buildAsyncClient()} respectively.
+ * This class provides a fluent builder API to help aid the configuration and instantiation Storage Blob clients.
*
*
* The following information must be provided on this builder:
@@ -46,8 +49,17 @@
*
*
*
- * Once all the configurations are set on this builder, call {@code .buildClient()} to create a
- * {@link BlobClient} or {@code .buildAsyncClient()} to create a {@link BlobAsyncClient}.
+ * Once all the configurations are set on this builder use the following mapping to construct the given client:
+ *
+ * - {@link BlobClientBuilder#buildBlobClient()} - {@link BlobClient}
+ * - {@link BlobClientBuilder#buildBlobAsyncClient()} - {@link BlobAsyncClient}
+ * - {@link BlobClientBuilder#buildAppendBlobClient()} - {@link AppendBlobClient}
+ * - {@link BlobClientBuilder#buildAppendBlobAsyncClient()} - {@link AppendBlobAsyncClient}
+ * - {@link BlobClientBuilder#buildBlockBlobClient()} - {@link BlockBlobClient}
+ * - {@link BlobClientBuilder#buildBlockBlobAsyncClient()} - {@link BlockBlobAsyncClient}
+ * - {@link BlobClientBuilder#buildPageBlobClient()} - {@link PageBlobClient}
+ * - {@link BlobClientBuilder#buildPageBlobAsyncClient()} - {@link PageBlobAsyncClient}
+ *
*/
public final class BlobClientBuilder {
private static final String ACCOUNT_NAME = "accountname";
@@ -70,8 +82,7 @@ public final class BlobClientBuilder {
private Configuration configuration;
/**
- * Creates a builder instance that is able to configure and construct {@link BlobClient BlobClients}
- * and {@link BlobAsyncClient BlobAsyncClients}.
+ * Creates a builder instance that is able to configure and construct Storage Blob clients.
*/
public BlobClientBuilder() {
retryOptions = new RequestRetryOptions();
@@ -120,53 +131,130 @@ private AzureBlobStorageBuilder buildImpl() {
}
/**
+ * Creates a {@link BlobClient} based on options set in the Builder. BlobClients are used to perform generic blob
+ * methods such as {@link BlobClient#download(OutputStream) download} and
+ * {@link BlobClient#getProperties() get properties}, use this when the blob type is unknown.
+ *
* @return a {@link BlobClient} created from the configurations in this builder.
+ * @throws NullPointerException If {@code endpoint}, {@code containerName}, or {@code blobName} is {@code null}.
*/
- public BlobClient buildClient() {
- return new BlobClient(buildAsyncClient());
+ public BlobClient buildBlobClient() {
+ return new BlobClient(buildBlobAsyncClient());
}
/**
+ * Creates a {@link BlobAsyncClient} based on options set in the Builder. BlobAsyncClients are used to perform
+ * generic blob methods such as {@link BlobAsyncClient#download() download} and
+ * {@link BlobAsyncClient#getProperties()}, use this when the blob type is unknown.
+ *
* @return a {@link BlobAsyncClient} created from the configurations in this builder.
+ * @throws NullPointerException If {@code endpoint}, {@code containerName}, or {@code blobName} is {@code null}.
*/
- public BlobAsyncClient buildAsyncClient() {
+ public BlobAsyncClient buildBlobAsyncClient() {
return new BlobAsyncClient(buildImpl(), snapshot);
}
+ /**
+ * Creates a {@link AppendBlobClient} based on options set in the Builder. AppendBlobClients are used to perform
+ * append blob specific operations such as {@link AppendBlobClient#appendBlock(InputStream, long) append block},
+ * only use this when the blob is known to be an append blob.
+ *
+ * @return a {@link AppendBlobClient} created from the configurations in this builder.
+ * @throws NullPointerException If {@code endpoint}, {@code containerName}, or {@code blobName} is {@code null}.
+ */
+ public AppendBlobClient buildAppendBlobClient() {
+ return new AppendBlobClient(buildAppendBlobAsyncClient());
+ }
+
+ /**
+ * Creates a {@link AppendBlobAsyncClient} based on options set in the Builder. AppendBlobAsyncClients are used to
+ * perform append blob specific operations such as {@link AppendBlobAsyncClient#appendBlock(Flux, long) append blob},
+ * only use this when the blob is known to be an append blob.
+ *
+ * @return a {@link AppendBlobAsyncClient} created from the configurations in this builder.
+ * @throws NullPointerException If {@code endpoint}, {@code containerName}, or {@code blobName} is {@code null}.
+ */
+ public AppendBlobAsyncClient buildAppendBlobAsyncClient() {
+ return new AppendBlobAsyncClient(buildImpl(), snapshot);
+ }
+
+ /**
+ * Creates a {@link BlockBlobClient} based on options set in the Builder. BlockBlobClients are used to perform
+ * generic upload operations such as {@link BlockBlobClient#uploadFromFile(String) upload from file} and block
+ * blob specific operations such as {@link BlockBlobClient#stageBlock(String, InputStream, long) stage block} and
+ * {@link BlockBlobClient#commitBlockList(List)}, only use this when the blob is known to be a block blob.
+ *
+ * @return a {@link BlockBlobClient} created from the configurations in this builder.
+ * @throws NullPointerException If {@code endpoint}, {@code containerName}, or {@code blobName} is {@code null}.
+ */
+ public BlockBlobClient buildBlockBlobClient() {
+ return new BlockBlobClient(buildBlockBlobAsyncClient());
+ }
+
+ /**
+ * Creates a {@link BlockBlobAsyncClient} based on options set in the Builder. BlockBlobAsyncClients are used to
+ * perform generic upload operations such as {@link BlockBlobAsyncClient#uploadFromFile(String) upload from file}
+ * and block blob specific operations such as {@link BlockBlobAsyncClient#stageBlock(String, Flux, long) stage block}
+ * and {@link BlockBlobAsyncClient#commitBlockList(List) commit block list}, only use this when the blob is known to
+ * be a block blob.
+ *
+ * @return a {@link BlockBlobAsyncClient} created from the configurations in this builder.
+ * @throws NullPointerException If {@code endpoint}, {@code containerName}, or {@code blobName} is {@code null}.
+ */
+ public BlockBlobAsyncClient buildBlockBlobAsyncClient() {
+ return new BlockBlobAsyncClient(buildImpl(), snapshot);
+ }
+
+ /**
+ * Creates a {@link PageBlobClient} based on options set in the Builder. PageBlobClients are used to perform page
+ * blob specific operations such as {@link PageBlobClient#uploadPages(PageRange, InputStream) upload pages} and
+ * {@link PageBlobClient#clearPages(PageRange) clear pages}, only use this when the blob is known to be a page blob.
+ *
+ * @return a {@link PageBlobClient} created from the configurations in this builder.
+ * @throws NullPointerException If {@code endpoint}, {@code containerName}, or {@code blobName} is {@code null}.
+ */
+ public PageBlobClient buildPageBlobClient() {
+ return new PageBlobClient(buildPageBlobAsyncClient());
+ }
+
+ /**
+ * Creates a {@link PageBlobAsyncClient} based on options set in the Builder. PageBlobAsyncClients are used to
+ * perform page blob specific operations such as {@link PageBlobAsyncClient#uploadPages(PageRange, Flux) upload pages}
+ * and {@link PageBlobAsyncClient#clearPages(PageRange) clear pages}, only use this when the blob is known to be a
+ * page blob.
+ *
+ * @return a {@link PageBlobAsyncClient} created from the configurations in this builder.
+ * @throws NullPointerException If {@code endpoint}, {@code containerName}, or {@code blobName} is {@code null}.
+ */
+ public PageBlobAsyncClient buildPageBlobAsyncClient() {
+ return new PageBlobAsyncClient(buildImpl(), snapshot);
+ }
+
/**
* Sets the service endpoint, additionally parses it for information (SAS token, container name, blob name)
* @param endpoint URL of the service
* @return the updated BlobClientBuilder object
- * @throws IllegalArgumentException If {@code endpoint} is a malformed URL.
+ * @throws IllegalArgumentException If {@code endpoint} is {@code null} or is a malformed URL.
*/
public BlobClientBuilder endpoint(String endpoint) {
- Objects.requireNonNull(endpoint);
- URL url;
try {
- url = new URL(endpoint);
+ URL url = new URL(endpoint);
BlobURLParts parts = URLParser.parse(url);
- this.endpoint = parts.scheme() + "://" + parts.host();
-
- if (parts.containerName() != null) {
- this.containerName = parts.containerName();
- }
-
- if (parts.blobName() != null) {
- this.blobName = parts.blobName();
- }
- if (parts.snapshot() != null) {
- this.snapshot = parts.snapshot();
+ this.endpoint = parts.scheme() + "://" + parts.host();
+ this.containerName = parts.containerName();
+ this.blobName = parts.blobName();
+ this.snapshot = parts.snapshot();
+
+ this.sasTokenCredential = SASTokenCredential.fromQueryParameters(parts.sasQueryParameters());
+ if (this.sasTokenCredential != null) {
+ this.tokenCredential = null;
+ this.sharedKeyCredential = null;
}
} catch (MalformedURLException ex) {
throw new IllegalArgumentException("The Azure Storage Blob endpoint url is malformed.");
}
- SASTokenCredential credential = SASTokenCredential.fromQuery(url.getQuery());
- if (credential != null) {
- this.credential(credential);
- }
-
return this;
}
@@ -174,9 +262,10 @@ public BlobClientBuilder endpoint(String endpoint) {
* Sets the name of the container this client is connecting to.
* @param containerName the name of the container
* @return the updated BlobClientBuilder object
+ * @throws NullPointerException If {@code containerName} is {@code null}
*/
public BlobClientBuilder containerName(String containerName) {
- this.containerName = containerName;
+ this.containerName = Objects.requireNonNull(containerName);
return this;
}
@@ -184,9 +273,10 @@ public BlobClientBuilder containerName(String containerName) {
* Sets the name of the blob this client is connecting to.
* @param blobName the name of the blob
* @return the updated BlobClientBuilder object
+ * @throws NullPointerException If {@code blobName} is {@code null}
*/
public BlobClientBuilder blobName(String blobName) {
- this.blobName = blobName;
+ this.blobName = Objects.requireNonNull(blobName);
return this;
}
@@ -204,9 +294,10 @@ public BlobClientBuilder snapshot(String snapshot) {
* Sets the credential used to authorize requests sent to the service
* @param credential authorization credential
* @return the updated BlobClientBuilder object
+ * @throws NullPointerException If {@code credential} is {@code null}
*/
public BlobClientBuilder credential(SharedKeyCredential credential) {
- this.sharedKeyCredential = credential;
+ this.sharedKeyCredential = Objects.requireNonNull(credential);
this.tokenCredential = null;
this.sasTokenCredential = null;
return this;
@@ -216,9 +307,10 @@ public BlobClientBuilder credential(SharedKeyCredential credential) {
* Sets the credential used to authorize requests sent to the service
* @param credential authorization credential
* @return the updated BlobClientBuilder object
+ * @throws NullPointerException If {@code credential} is {@code null}
*/
public BlobClientBuilder credential(TokenCredential credential) {
- this.tokenCredential = credential;
+ this.tokenCredential = Objects.requireNonNull(credential);
this.sharedKeyCredential = null;
this.sasTokenCredential = null;
return this;
@@ -228,9 +320,10 @@ public BlobClientBuilder credential(TokenCredential credential) {
* Sets the credential used to authorize requests sent to the service
* @param credential authorization credential
* @return the updated BlobClientBuilder object
+ * @throws NullPointerException If {@code credential} is {@code null}
*/
public BlobClientBuilder credential(SASTokenCredential credential) {
- this.sasTokenCredential = credential;
+ this.sasTokenCredential = Objects.requireNonNull(credential);
this.sharedKeyCredential = null;
this.tokenCredential = null;
return this;
@@ -251,6 +344,7 @@ public BlobClientBuilder anonymousCredential() {
* Sets the connection string for the service, parses it for authentication information (account name, account key)
* @param connectionString connection string from access keys section
* @return the updated BlobClientBuilder object
+ * @throws NullPointerException If {@code connectionString} is {@code null}
* @throws IllegalArgumentException If {@code connectionString} doesn't contain AccountName or AccountKey.
*/
public BlobClientBuilder connectionString(String connectionString) {
@@ -284,9 +378,10 @@ public BlobClientBuilder connectionString(String connectionString) {
* Sets the http client used to send service requests
* @param httpClient http client to send requests
* @return the updated BlobClientBuilder object
+ * @throws NullPointerException If {@code httpClient} is {@code null}
*/
public BlobClientBuilder httpClient(HttpClient httpClient) {
- this.httpClient = httpClient;
+ this.httpClient = Objects.requireNonNull(httpClient);
return this;
}
@@ -294,9 +389,10 @@ public BlobClientBuilder httpClient(HttpClient httpClient) {
* Adds a pipeline policy to apply on each request sent
* @param pipelinePolicy a pipeline policy
* @return the updated BlobClientBuilder object
+ * @throws NullPointerException If {@code pipelinePolicy} is {@code null}
*/
public BlobClientBuilder addPolicy(HttpPipelinePolicy pipelinePolicy) {
- this.policies.add(pipelinePolicy);
+ this.policies.add(Objects.requireNonNull(pipelinePolicy));
return this;
}
@@ -325,9 +421,10 @@ public BlobClientBuilder configuration(Configuration configuration) {
* Sets the request retry options for all the requests made through the client.
* @param retryOptions the options to configure retry behaviors
* @return the updated BlobClientBuilder object
+ * @throws NullPointerException If {@code retryOptions} is {@code null}
*/
public BlobClientBuilder retryOptions(RequestRetryOptions retryOptions) {
- this.retryOptions = retryOptions;
+ this.retryOptions = Objects.requireNonNull(retryOptions);
return this;
}
}
diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobInputStream.java b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobInputStream.java
index 2e093f50738f2..1a990e179688b 100644
--- a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobInputStream.java
+++ b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobInputStream.java
@@ -189,7 +189,7 @@ public synchronized void close() throws IOException {
*/
private synchronized void dispatchRead(final int readLength) throws IOException {
try {
- this.currentBuffer = this.blobClient.blobAsyncRawClient.download(new BlobRange(this.currentAbsoluteReadPosition, (long) readLength), this.accessCondition, false)
+ this.currentBuffer = this.blobClient.download(new BlobRange(this.currentAbsoluteReadPosition, (long) readLength), this.accessCondition, false)
.flatMap(res -> ByteBufFlux.fromInbound(res.body(null)).aggregate().asByteBuffer())
.block();
diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobOutputStream.java b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobOutputStream.java
index 176fe06c321d1..c733a580f2500 100644
--- a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobOutputStream.java
+++ b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobOutputStream.java
@@ -295,7 +295,7 @@ private Mono writePages(Flux pageData, long offset, long writeLen
PageBlobAccessConditions pageBlobAccessConditions = accessCondition == null ? null : new PageBlobAccessConditions().leaseAccessConditions(accessCondition.leaseAccessConditions()).modifiedAccessConditions(accessCondition.modifiedAccessConditions());
- return blobRef.pageBlobAsyncRawClient.uploadPages(new PageRange().start(offset).end(offset + writeLength - 1), pageData, pageBlobAccessConditions)
+ return blobRef.uploadPages(new PageRange().start(offset).end(offset + writeLength - 1), pageData, pageBlobAccessConditions)
.then()
.onErrorResume(t -> t instanceof StorageException, e -> {
this.lastError = new IOException(e);
@@ -312,7 +312,7 @@ private Mono appendBlock(Flux blockData, long offset, long writeL
this.appendPositionAccessConditions.appendPosition(offset);
AppendBlobAccessConditions appendBlobAccessConditions = accessCondition == null ? null : new AppendBlobAccessConditions().leaseAccessConditions(accessCondition.leaseAccessConditions()).modifiedAccessConditions(accessCondition.modifiedAccessConditions());
- return blobRef.appendBlobAsyncRawClient.appendBlock(blockData, writeLength, appendBlobAccessConditions)
+ return blobRef.appendBlock(blockData, writeLength, appendBlobAccessConditions)
.then()
.onErrorResume(t -> t instanceof IOException || t instanceof StorageException, e -> {
this.lastError = new IOException(e);
diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobURLParts.java b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobURLParts.java
index 473d998c446b2..1200e960f7501 100644
--- a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobURLParts.java
+++ b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobURLParts.java
@@ -76,14 +76,14 @@ public BlobURLParts host(String host) {
}
/**
- * The container name or {@code null} if a {@link StorageAsyncRawClient} was parsed.
+ * The container name or {@code null} if a {@link StorageAsyncClient} was parsed.
*/
public String containerName() {
return containerName;
}
/**
- * The container name or {@code null} if a {@link StorageAsyncRawClient} was parsed.
+ * The container name or {@code null} if a {@link StorageAsyncClient} was parsed.
*/
public BlobURLParts containerName(String containerName) {
this.containerName = containerName;
@@ -91,14 +91,14 @@ public BlobURLParts containerName(String containerName) {
}
/**
- * The blob name or {@code null} if a {@link StorageAsyncRawClient} or {@link ContainerAsyncClient} was parsed.
+ * The blob name or {@code null} if a {@link StorageAsyncClient} or {@link ContainerAsyncClient} was parsed.
*/
public String blobName() {
return blobName;
}
/**
- * The blob name or {@code null} if a {@link StorageAsyncRawClient} or {@link ContainerAsyncClient} was parsed.
+ * The blob name or {@code null} if a {@link StorageAsyncClient} or {@link ContainerAsyncClient} was parsed.
*/
public BlobURLParts blobName(String blobName) {
this.blobName = blobName;
diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobAsyncClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobAsyncClient.java
index ada7a125d4ef1..cdb0a06fa68e2 100644
--- a/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobAsyncClient.java
+++ b/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobAsyncClient.java
@@ -8,6 +8,7 @@
import com.azure.core.http.rest.SimpleResponse;
import com.azure.core.http.rest.VoidResponse;
import com.azure.core.implementation.util.FluxUtil;
+import com.azure.core.util.Context;
import com.azure.storage.blob.implementation.AzureBlobStorageBuilder;
import com.azure.storage.blob.models.BlobAccessConditions;
import com.azure.storage.blob.models.BlobHTTPHeaders;
@@ -15,11 +16,11 @@
import com.azure.storage.blob.models.BlockBlobItem;
import com.azure.storage.blob.models.BlockItem;
import com.azure.storage.blob.models.BlockListType;
+import com.azure.storage.blob.models.BlockLookupList;
import com.azure.storage.blob.models.LeaseAccessConditions;
import com.azure.storage.blob.models.Metadata;
import com.azure.storage.blob.models.SourceModifiedAccessConditions;
import io.netty.buffer.ByteBuf;
-import io.netty.buffer.Unpooled;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -27,7 +28,6 @@
import java.io.IOException;
import java.io.UncheckedIOException;
import java.net.URL;
-import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
@@ -39,8 +39,10 @@
import java.util.TreeMap;
import java.util.UUID;
+import static com.azure.storage.blob.Utility.postProcessResponse;
+
/**
- * Client to a block blob. It may only be instantiated through a {@link BlockBlobClientBuilder}, via
+ * Client to a block blob. It may only be instantiated through a {@link BlobClientBuilder}, via
* the method {@link BlobAsyncClient#asBlockBlobAsyncClient()}, or via the method
* {@link ContainerAsyncClient#getBlockBlobAsyncClient(String)}. This class does not hold
* any state about a particular blob, but is instead a convenient way of sending appropriate
@@ -66,8 +68,6 @@ public final class BlockBlobAsyncClient extends BlobAsyncClient {
static final int BLOB_DEFAULT_UPLOAD_BLOCK_SIZE = 4 * Constants.MB;
static final int BLOB_MAX_UPLOAD_BLOCK_SIZE = 100 * Constants.MB;
- final BlockBlobAsyncRawClient blockBlobAsyncRawClient;
-
/**
* Indicates the maximum number of bytes that can be sent in a call to upload.
*/
@@ -84,12 +84,11 @@ public final class BlockBlobAsyncClient extends BlobAsyncClient {
public static final int MAX_BLOCKS = 50000;
/**
- * Package-private constructor for use by {@link BlockBlobClientBuilder}.
+ * Package-private constructor for use by {@link BlobClientBuilder}.
* @param azureBlobStorageBuilder the API client builder for blob storage API
*/
BlockBlobAsyncClient(AzureBlobStorageBuilder azureBlobStorageBuilder, String snapshot) {
super(azureBlobStorageBuilder, snapshot);
- this.blockBlobAsyncRawClient = new BlockBlobAsyncRawClient(azureBlobStorageBuilder.build(), snapshot);
}
/**
@@ -114,7 +113,7 @@ public final class BlockBlobAsyncClient extends BlobAsyncClient {
* @return
* A reactive response containing the information of the uploaded block blob.
*/
- public Mono> upload(Flux data, long length) {
+ public Mono> upload(Flux data, long length) {
return this.upload(data, length, null, null, null);
}
@@ -146,10 +145,15 @@ public Mono> upload(Flux data, long length)
* @return
* A reactive response containing the information of the uploaded block blob.
*/
- public Mono> upload(Flux data, long length, BlobHTTPHeaders headers,
+ public Mono> upload(Flux data, long length, BlobHTTPHeaders headers,
Metadata metadata, BlobAccessConditions accessConditions) {
- return blockBlobAsyncRawClient
- .upload(data.map(Unpooled::wrappedBuffer), length, headers, metadata, accessConditions)
+ metadata = metadata == null ? new Metadata() : metadata;
+ accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions;
+
+ return postProcessResponse(this.azureBlobStorage.blockBlobs().uploadWithRestResponseAsync(null,
+ null, data, length, null, metadata, null, null,
+ null, null, headers, accessConditions.leaseAccessConditions(),
+ accessConditions.modifiedAccessConditions(), Context.NONE))
.map(rb -> new SimpleResponse<>(rb, new BlockBlobItem(rb.deserializedHeaders())));
}
@@ -291,8 +295,9 @@ public Mono stageBlock(String base64BlockID, Flux data,
*/
public Mono stageBlock(String base64BlockID, Flux data, long length,
LeaseAccessConditions leaseAccessConditions) {
- return blockBlobAsyncRawClient
- .stageBlock(base64BlockID, data, length, leaseAccessConditions)
+ return postProcessResponse(this.azureBlobStorage.blockBlobs().stageBlockWithRestResponseAsync(null,
+ null, base64BlockID, length, data, null, null, null,
+ null, null, null, leaseAccessConditions, Context.NONE))
.map(VoidResponse::new);
}
@@ -349,8 +354,13 @@ public Mono stageBlockFromURL(String base64BlockID, URL sourceURL,
public Mono stageBlockFromURL(String base64BlockID, URL sourceURL,
BlobRange sourceRange, byte[] sourceContentMD5, LeaseAccessConditions leaseAccessConditions,
SourceModifiedAccessConditions sourceModifiedAccessConditions) {
- return blockBlobAsyncRawClient
- .stageBlockFromURL(base64BlockID, sourceURL, sourceRange, sourceContentMD5, leaseAccessConditions, sourceModifiedAccessConditions)
+ sourceRange = sourceRange == null ? new BlobRange(0) : sourceRange;
+
+ return postProcessResponse(
+ this.azureBlobStorage.blockBlobs().stageBlockFromURLWithRestResponseAsync(null, null,
+ base64BlockID, 0, sourceURL, sourceRange.toHeaderValue(), sourceContentMD5, null,
+ null, null, null, null,
+ leaseAccessConditions, sourceModifiedAccessConditions, Context.NONE))
.map(VoidResponse::new);
}
@@ -386,8 +396,9 @@ public Flux listBlocks(BlockListType listType) {
*/
public Flux listBlocks(BlockListType listType,
LeaseAccessConditions leaseAccessConditions) {
- return blockBlobAsyncRawClient
- .listBlocks(listType, leaseAccessConditions)
+ return postProcessResponse(this.azureBlobStorage.blockBlobs().getBlockListWithRestResponseAsync(
+ null, null, listType, snapshot, null, null, null,
+ leaseAccessConditions, Context.NONE))
.map(ResponseBase::value)
.flatMapMany(bl -> {
Flux committed = Flux.fromIterable(bl.committedBlocks())
@@ -440,8 +451,13 @@ public Mono> commitBlockList(List base64BlockIDs
*/
public Mono> commitBlockList(List base64BlockIDs,
BlobHTTPHeaders headers, Metadata metadata, BlobAccessConditions accessConditions) {
- return blockBlobAsyncRawClient
- .commitBlockList(base64BlockIDs, headers, metadata, accessConditions)
+ metadata = metadata == null ? new Metadata() : metadata;
+ accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions;
+
+ return postProcessResponse(this.azureBlobStorage.blockBlobs().commitBlockListWithRestResponseAsync(
+ null, null, new BlockLookupList().latest(base64BlockIDs), null, metadata,
+ null, null, null, null, headers,
+ accessConditions.leaseAccessConditions(), accessConditions.modifiedAccessConditions(), Context.NONE))
.map(rb -> new SimpleResponse<>(rb, new BlockBlobItem(rb.deserializedHeaders())));
}
}
diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobAsyncRawClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobAsyncRawClient.java
deleted file mode 100644
index 03b7e650167b6..0000000000000
--- a/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobAsyncRawClient.java
+++ /dev/null
@@ -1,364 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package com.azure.storage.blob;
-
-import com.azure.core.util.Context;
-import com.azure.storage.blob.implementation.AzureBlobStorageImpl;
-import com.azure.storage.blob.models.BlobAccessConditions;
-import com.azure.storage.blob.models.BlobHTTPHeaders;
-import com.azure.storage.blob.models.BlobRange;
-import com.azure.storage.blob.models.BlockBlobsCommitBlockListResponse;
-import com.azure.storage.blob.models.BlockBlobsGetBlockListResponse;
-import com.azure.storage.blob.models.BlockBlobsStageBlockFromURLResponse;
-import com.azure.storage.blob.models.BlockBlobsStageBlockResponse;
-import com.azure.storage.blob.models.BlockBlobsUploadResponse;
-import com.azure.storage.blob.models.BlockListType;
-import com.azure.storage.blob.models.BlockLookupList;
-import com.azure.storage.blob.models.LeaseAccessConditions;
-import com.azure.storage.blob.models.Metadata;
-import com.azure.storage.blob.models.SourceModifiedAccessConditions;
-import io.netty.buffer.ByteBuf;
-import reactor.core.publisher.Flux;
-import reactor.core.publisher.Mono;
-
-import java.net.URL;
-import java.util.List;
-
-import static com.azure.storage.blob.Utility.postProcessResponse;
-
-/**
- * Represents a URL to a block blob. It may be obtained by direct construction or via the create method on a
- * {@link ContainerAsyncClient} object. This class does not hold any state about a particular blob but is instead a convenient
- * way of sending off appropriate requests to the resource on the service. Please refer to the
- * Azure Docs
- * for more information on block blobs.
- */
-final class BlockBlobAsyncRawClient extends BlobAsyncRawClient {
-
- /**
- * Indicates the maximum number of bytes that can be sent in a call to upload.
- */
- public static final int MAX_UPLOAD_BLOB_BYTES = 256 * Constants.MB;
-
- /**
- * Indicates the maximum number of bytes that can be sent in a call to stageBlock.
- */
- public static final int MAX_STAGE_BLOCK_BYTES = 100 * Constants.MB;
-
- /**
- * Indicates the maximum number of blocks allowed in a block blob.
- */
- public static final int MAX_BLOCKS = 50000;
-
- /**
- * Creates a {@code BlockBlobAsyncRawClient} object pointing to the account specified by the URL and using the provided
- */
- BlockBlobAsyncRawClient(AzureBlobStorageImpl azureBlobStorage, String snapshot) {
- super(azureBlobStorage, snapshot);
- }
-
-
- /**
- * Creates a new block blob, or updates the content of an existing block blob.
- * Updating an existing block blob overwrites any existing metadata on the blob. Partial updates are not
- * supported with PutBlob; the content of the existing blob is overwritten with the new content. To
- * perform a partial update of a block blob's, use PutBlock and PutBlockList.
- * For more information, see the
- * Azure Docs.
- *
- * Note that the data passed must be replayable if retries are enabled (the default). In other words, the
- * {@code Flux} must produce the same data each time it is subscribed to.
- *
- *
- * @param data
- * The data to write to the blob. Note that this {@code Flux} must be replayable if retries are enabled
- * (the default). In other words, the Flowable must produce the same data each time it is subscribed to.
- * @param length
- * The exact length of the data. It is important that this value match precisely the length of the data
- * emitted by the {@code Flux}.
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=upload_download "Sample code for BlockBlobAsyncRawClient.upload")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono upload(Flux data, long length) {
- return this.upload(data, length, null, null, null);
- }
-
- /**
- * Creates a new block blob, or updates the content of an existing block blob.
- * Updating an existing block blob overwrites any existing metadata on the blob. Partial updates are not
- * supported with PutBlob; the content of the existing blob is overwritten with the new content. To
- * perform a partial update of a block blob's, use PutBlock and PutBlockList.
- * For more information, see the
- * Azure Docs.
- *
- * Note that the data passed must be replayable if retries are enabled (the default). In other words, the
- * {@code Flux} must produce the same data each time it is subscribed to.
- *
- *
- * @param data
- * The data to write to the blob. Note that this {@code Flux} must be replayable if retries are enabled
- * (the default). In other words, the Flowable must produce the same data each time it is subscribed to.
- * @param length
- * The exact length of the data. It is important that this value match precisely the length of the data
- * emitted by the {@code Flux}.
- * @param headers
- * {@link BlobHTTPHeaders}
- * @param metadata
- * {@link Metadata}
- * @param accessConditions
- * {@link BlobAccessConditions}
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=upload_download "Sample code for BlockBlobAsyncRawClient.upload")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono upload(Flux data, long length, BlobHTTPHeaders headers,
- Metadata metadata, BlobAccessConditions accessConditions) {
- metadata = metadata == null ? new Metadata() : metadata;
- accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions;
-
- return postProcessResponse(this.azureBlobStorage.blockBlobs().uploadWithRestResponseAsync(null,
- null, data, length, null, metadata, null, null,
- null, null, headers, accessConditions.leaseAccessConditions(),
- accessConditions.modifiedAccessConditions(), Context.NONE));
- }
-
- /**
- * Uploads the specified block to the block blob's "staging area" to be later committed by a call to
- * commitBlockList. For more information, see the
- * Azure Docs.
- *
- * Note that the data passed must be replayable if retries are enabled (the default). In other words, the
- * {@code Flux} must produce the same data each time it is subscribed to.
- *
- * @param base64BlockID
- * A Base64 encoded {@code String} that specifies the ID for this block. Note that all block ids for a given
- * blob must be the same length.
- * @param data
- * The data to write to the block. Note that this {@code Flux} must be replayable if retries are enabled
- * (the default). In other words, the Flowable must produce the same data each time it is subscribed to.
- * @param length
- * The exact length of the data. It is important that this value match precisely the length of the data
- * emitted by the {@code Flux}.
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blocks "Sample code for BlockBlobAsyncRawClient.stageBlock")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono stageBlock(String base64BlockID, Flux data,
- long length) {
- return this.stageBlock(base64BlockID, data, length, null);
- }
-
- /**
- * Uploads the specified block to the block blob's "staging area" to be later committed by a call to
- * commitBlockList. For more information, see the
- * Azure Docs.
- *
- * Note that the data passed must be replayable if retries are enabled (the default). In other words, the
- * {@code Flux} must produce the same data each time it is subscribed to.
- *
- * @param base64BlockID
- * A Base64 encoded {@code String} that specifies the ID for this block. Note that all block ids for a given
- * blob must be the same length.
- * @param data
- * The data to write to the block. Note that this {@code Flux} must be replayable if retries are enabled
- * (the default). In other words, the Flowable must produce the same data each time it is subscribed to.
- * @param length
- * The exact length of the data. It is important that this value match precisely the length of the data
- * emitted by the {@code Flux}.
- * @param leaseAccessConditions
- * By setting lease access conditions, requests will fail if the provided lease does not match the active
- * lease on the blob.
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blocks "Sample code for BlockBlobAsyncRawClient.stageBlock")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono stageBlock(String base64BlockID, Flux data, long length,
- LeaseAccessConditions leaseAccessConditions) {
- return postProcessResponse(this.azureBlobStorage.blockBlobs().stageBlockWithRestResponseAsync(null,
- null, base64BlockID, length, data, null, null, null,
- null, null, null, leaseAccessConditions, Context.NONE));
- }
-
- /**
- * Creates a new block to be committed as part of a blob where the contents are read from a URL. For more
- * information, see the Azure Docs.
- *
- * @param base64BlockID
- * A Base64 encoded {@code String} that specifies the ID for this block. Note that all block ids for a given
- * blob must be the same length.
- * @param sourceURL
- * The url to the blob that will be the source of the copy. A source blob in the same storage account can be
- * authenticated via Shared Key. However, if the source is a blob in another account, the source blob must
- * either be public or must be authenticated via a shared access signature. If the source blob is public, no
- * authentication is required to perform the operation.
- * @param sourceRange
- * {@link BlobRange}
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=block_from_url "Sample code for BlockBlobAsyncRawClient.stageBlockFromURL")]
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono stageBlockFromURL(String base64BlockID, URL sourceURL,
- BlobRange sourceRange) {
- return this.stageBlockFromURL(base64BlockID, sourceURL, sourceRange, null,
- null, null);
- }
-
- /**
- * Creates a new block to be committed as part of a blob where the contents are read from a URL. For more
- * information, see the Azure Docs.
- *
- * @param base64BlockID
- * A Base64 encoded {@code String} that specifies the ID for this block. Note that all block ids for a given
- * blob must be the same length.
- * @param sourceURL
- * The url to the blob that will be the source of the copy. A source blob in the same storage account can
- * be authenticated via Shared Key. However, if the source is a blob in another account, the source blob
- * must either be public or must be authenticated via a shared access signature. If the source blob is
- * public, no authentication is required to perform the operation.
- * @param sourceRange
- * {@link BlobRange}
- * @param sourceContentMD5
- * An MD5 hash of the block content from the source blob. If specified, the service will calculate the MD5
- * of the received data and fail the request if it does not match the provided MD5.
- * @param leaseAccessConditions
- * By setting lease access conditions, requests will fail if the provided lease does not match the active
- * lease on the blob.
- * @param sourceModifiedAccessConditions
- * {@link SourceModifiedAccessConditions}
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=block_from_url "Sample code for BlockBlobAsyncRawClient.stageBlockFromURL")]
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono stageBlockFromURL(String base64BlockID, URL sourceURL,
- BlobRange sourceRange, byte[] sourceContentMD5, LeaseAccessConditions leaseAccessConditions,
- SourceModifiedAccessConditions sourceModifiedAccessConditions) {
- sourceRange = sourceRange == null ? new BlobRange(0) : sourceRange;
-
- return postProcessResponse(
- this.azureBlobStorage.blockBlobs().stageBlockFromURLWithRestResponseAsync(null, null,
- base64BlockID, 0, sourceURL, sourceRange.toHeaderValue(), sourceContentMD5, null,
- null, null, null, null,
- leaseAccessConditions, sourceModifiedAccessConditions, Context.NONE));
- }
-
- /**
- * Returns the list of blocks that have been uploaded as part of a block blob using the specified block list filter.
- * For more information, see the
- * Azure Docs.
- *
- * @param listType
- * Specifies which type of blocks to return.
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blocks "Sample code for BlockBlobAsyncRawClient.listBlocks")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono listBlocks(BlockListType listType) {
- return this.listBlocks(listType, null);
- }
-
- /**
- * Returns the list of blocks that have been uploaded as part of a block blob using the specified block list filter.
- * For more information, see the
- * Azure Docs.
- *
- * @param listType
- * Specifies which type of blocks to return.
- * @param leaseAccessConditions
- * By setting lease access conditions, requests will fail if the provided lease does not match the active
- * lease on the blob.
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blocks "Sample code for BlockBlobAsyncRawClient.listBlocks")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono listBlocks(BlockListType listType,
- LeaseAccessConditions leaseAccessConditions) {
- return postProcessResponse(this.azureBlobStorage.blockBlobs().getBlockListWithRestResponseAsync(
- null, null, listType, snapshot, null, null, null,
- leaseAccessConditions, Context.NONE));
- }
-
- /**
- * Writes a blob by specifying the list of block IDs that are to make up the blob.
- * In order to be written as part of a blob, a block must have been successfully written
- * to the server in a prior stageBlock operation. You can call commitBlockList to update a blob
- * by uploading only those blocks that have changed, then committing the new and existing
- * blocks together. Any blocks not specified in the block list and permanently deleted.
- * For more information, see the
- * Azure Docs.
- *
- *
- * @param base64BlockIDs
- * A list of base64 encode {@code String}s that specifies the block IDs to be committed.
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blocks "Sample code for BlockBlobAsyncRawClient.commitBlockList")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono commitBlockList(List base64BlockIDs) {
- return this.commitBlockList(base64BlockIDs, null, null, null);
- }
-
- /**
- * Writes a blob by specifying the list of block IDs that are to make up the blob.
- * In order to be written as part of a blob, a block must have been successfully written
- * to the server in a prior stageBlock operation. You can call commitBlockList to update a blob
- * by uploading only those blocks that have changed, then committing the new and existing
- * blocks together. Any blocks not specified in the block list and permanently deleted.
- * For more information, see the
- * Azure Docs.
- *
- *
- * @param base64BlockIDs
- * A list of base64 encode {@code String}s that specifies the block IDs to be committed.
- * @param headers
- * {@link BlobHTTPHeaders}
- * @param metadata
- * {@link Metadata}
- * @param accessConditions
- * {@link BlobAccessConditions}
- *
- * @return Emits the successful response.
- *
- * @apiNote ## Sample Code \n
- * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blocks "Sample code for BlockBlobAsyncRawClient.commitBlockList")] \n
- * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java)
- */
- public Mono commitBlockList(List base64BlockIDs,
- BlobHTTPHeaders headers, Metadata metadata, BlobAccessConditions accessConditions) {
- metadata = metadata == null ? new Metadata() : metadata;
- accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions;
-
- return postProcessResponse(this.azureBlobStorage.blockBlobs().commitBlockListWithRestResponseAsync(
- null, null, new BlockLookupList().latest(base64BlockIDs), null, metadata,
- null, null, null, null, headers,
- accessConditions.leaseAccessConditions(), accessConditions.modifiedAccessConditions(), Context.NONE));
- }
-}
diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobClient.java
index 9dced1f87022b..6af92555c2b00 100644
--- a/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobClient.java
+++ b/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobClient.java
@@ -4,7 +4,6 @@
package com.azure.storage.blob;
import com.azure.core.http.rest.Response;
-import com.azure.core.http.rest.SimpleResponse;
import com.azure.core.http.rest.VoidResponse;
import com.azure.storage.blob.models.BlobAccessConditions;
import com.azure.storage.blob.models.BlobHTTPHeaders;
@@ -29,7 +28,7 @@
import java.util.List;
/**
- * Client to a block blob. It may only be instantiated through a {@link BlockBlobClientBuilder}, via
+ * Client to a block blob. It may only be instantiated through a {@link BlobClientBuilder}, via
* the method {@link BlobClient#asBlockBlobClient()}, or via the method
* {@link ContainerClient#getBlockBlobClient(String)}. This class does not hold
* any state about a particular blob, but is instead a convenient way of sending appropriate
@@ -44,25 +43,25 @@
* for more information.
*/
public final class BlockBlobClient extends BlobClient {
+ private final BlockBlobAsyncClient blockBlobAsyncClient;
- private BlockBlobAsyncClient blockBlobAsyncClient;
/**
* Indicates the maximum number of bytes that can be sent in a call to upload.
*/
- public static final int MAX_UPLOAD_BLOB_BYTES = 256 * Constants.MB;
+ public static final int MAX_UPLOAD_BLOB_BYTES = BlockBlobAsyncClient.MAX_UPLOAD_BLOB_BYTES;
/**
* Indicates the maximum number of bytes that can be sent in a call to stageBlock.
*/
- public static final int MAX_STAGE_BLOCK_BYTES = 100 * Constants.MB;
+ public static final int MAX_STAGE_BLOCK_BYTES = BlockBlobAsyncClient.MAX_STAGE_BLOCK_BYTES;
/**
* Indicates the maximum number of blocks allowed in a block blob.
*/
- public static final int MAX_BLOCKS = 50000;
+ public static final int MAX_BLOCKS = BlockBlobAsyncClient.MAX_BLOCKS;
/**
- * Package-private constructor for use by {@link BlockBlobClientBuilder}.
+ * Package-private constructor for use by {@link BlobClientBuilder}.
* @param blockBlobAsyncClient the async block blob client
*/
BlockBlobClient(BlockBlobAsyncClient blockBlobAsyncClient) {
@@ -161,9 +160,8 @@ public Response upload(InputStream data, long length, BlobHTTPHea
return ByteBufAllocator.DEFAULT.buffer((int) count).writeBytes(cache);
}));
- Mono> upload = blockBlobAsyncClient.blockBlobAsyncRawClient
- .upload(fbb.subscribeOn(Schedulers.elastic()), length, headers, metadata, accessConditions)
- .map(rb -> new SimpleResponse<>(rb, new BlockBlobItem(rb.deserializedHeaders())));
+ Mono> upload = blockBlobAsyncClient
+ .upload(fbb.subscribeOn(Schedulers.elastic()), length, headers, metadata, accessConditions);
try {
return Utility.blockWithOptionalTimeout(upload, timeout);
diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobClientBuilder.java b/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobClientBuilder.java
deleted file mode 100644
index 4774228c27648..0000000000000
--- a/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobClientBuilder.java
+++ /dev/null
@@ -1,337 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-package com.azure.storage.blob;
-
-import com.azure.core.credentials.TokenCredential;
-import com.azure.core.http.HttpClient;
-import com.azure.core.http.HttpPipeline;
-import com.azure.core.http.policy.AddDatePolicy;
-import com.azure.core.http.policy.BearerTokenAuthenticationPolicy;
-import com.azure.core.http.policy.HttpLogDetailLevel;
-import com.azure.core.http.policy.HttpLoggingPolicy;
-import com.azure.core.http.policy.HttpPipelinePolicy;
-import com.azure.core.http.policy.RequestIdPolicy;
-import com.azure.core.http.policy.UserAgentPolicy;
-import com.azure.core.implementation.util.ImplUtils;
-import com.azure.core.util.configuration.Configuration;
-import com.azure.core.util.configuration.ConfigurationManager;
-import com.azure.storage.blob.implementation.AzureBlobStorageBuilder;
-import com.azure.storage.common.credentials.SASTokenCredential;
-import com.azure.storage.common.credentials.SharedKeyCredential;
-import com.azure.storage.common.policy.RequestRetryOptions;
-import com.azure.storage.common.policy.RequestRetryPolicy;
-import com.azure.storage.common.policy.SASTokenCredentialPolicy;
-import com.azure.storage.common.policy.SharedKeyCredentialPolicy;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Objects;
-
-/**
- * Fluent BlockBlobClientBuilder for instantiating a {@link BlockBlobClient} or {@link BlockBlobAsyncClient}
- * using {@link BlockBlobClientBuilder#buildClient()} or {@link BlockBlobClientBuilder#buildAsyncClient()} respectively.
- *
- *
- * The following information must be provided on this builder:
- *
- *
- * - the endpoint through {@code .endpoint()}, including the container name and blob name, in the format of {@code https://{accountName}.blob.core.windows.net/{containerName}/{blobName}}.
- *
- the credential through {@code .credential()} or {@code .connectionString()} if the container is not publicly accessible.
- *
- *
- *
- * Once all the configurations are set on this builder, call {@code .buildClient()} to create a
- * {@link BlockBlobClient} or {@code .buildAsyncClient()} to create a {@link BlockBlobAsyncClient}.
- */
-public final class BlockBlobClientBuilder {
- private static final String ACCOUNT_NAME = "accountname";
- private static final String ACCOUNT_KEY = "accountkey";
- private static final String ENDPOINT_PROTOCOL = "defaultendpointsprotocol";
- private static final String ENDPOINT_SUFFIX = "endpointsuffix";
-
- private final List policies;
-
- private String endpoint;
- private String containerName;
- private String blobName;
- private String snapshot;
- private SharedKeyCredential sharedKeyCredential;
- private TokenCredential tokenCredential;
- private SASTokenCredential sasTokenCredential;
- private HttpClient httpClient;
- private HttpLogDetailLevel logLevel;
- private RequestRetryOptions retryOptions;
- private Configuration configuration;
-
- /**
- * Creates a builder instance that is able to configure and construct {@link BlockBlobClient BlockBlobClients}
- * and {@link BlockBlobAsyncClient BlockBlobAsyncClients}.
- */
- public BlockBlobClientBuilder() {
- retryOptions = new RequestRetryOptions();
- logLevel = HttpLogDetailLevel.NONE;
- policies = new ArrayList<>();
- }
-
- /**
- * Constructs an instance of BlockBlobAsyncClient based on the configurations stored in the appendBlobClientBuilder.
- * @return a new client instance
- */
- private AzureBlobStorageBuilder buildImpl() {
- Objects.requireNonNull(endpoint);
- Objects.requireNonNull(containerName);
- Objects.requireNonNull(blobName);
-
- // Closest to API goes first, closest to wire goes last.
- final List policies = new ArrayList<>();
-
- if (configuration == null) {
- configuration = ConfigurationManager.getConfiguration();
- }
- policies.add(new UserAgentPolicy(BlobConfiguration.NAME, BlobConfiguration.VERSION, configuration));
- policies.add(new RequestIdPolicy());
- policies.add(new AddDatePolicy());
-
- if (sharedKeyCredential != null) {
- policies.add(new SharedKeyCredentialPolicy(sharedKeyCredential));
- } else if (tokenCredential != null) {
- policies.add(new BearerTokenAuthenticationPolicy(tokenCredential, String.format("%s/.default", endpoint)));
- } else if (sasTokenCredential != null) {
- policies.add(new SASTokenCredentialPolicy(sasTokenCredential));
- } else {
- policies.add(new AnonymousCredentialPolicy());
- }
-
- policies.add(new RequestRetryPolicy(retryOptions));
-
- policies.addAll(this.policies);
- policies.add(new HttpLoggingPolicy(logLevel));
-
- HttpPipeline pipeline = HttpPipeline.builder()
- .policies(policies.toArray(new HttpPipelinePolicy[0]))
- .httpClient(httpClient)
- .build();
-
- return new AzureBlobStorageBuilder()
- .url(String.format("%s/%s/%s", endpoint, containerName, blobName))
- .pipeline(pipeline);
- }
-
- /**
- * @return a {@link BlockBlobClient} created from the configurations in this builder.
- */
- public BlockBlobClient buildClient() {
- return new BlockBlobClient(buildAsyncClient());
- }
-
- /**
- * @return a {@link BlockBlobAsyncClient} created from the configurations in this builder.
- */
- public BlockBlobAsyncClient buildAsyncClient() {
- return new BlockBlobAsyncClient(buildImpl(), snapshot);
- }
-
- /**
- * Sets the service endpoint, additionally parses it for information (SAS token, container name, blob name)
- * @param endpoint URL of the service
- * @return the updated BlockBlobClientBuilder object
- * @throws IllegalArgumentException If {@code endpoint} is a malformed URL.
- */
- public BlockBlobClientBuilder endpoint(String endpoint) {
- Objects.requireNonNull(endpoint);
- URL url;
- try {
- url = new URL(endpoint);
- BlobURLParts parts = URLParser.parse(url);
- this.endpoint = parts.scheme() + "://" + parts.host();
-
- if (parts.containerName() != null) {
- this.containerName = parts.containerName();
- }
-
- if (parts.blobName() != null) {
- this.blobName = parts.blobName();
- }
-
- if (parts.snapshot() != null) {
- this.snapshot = parts.snapshot();
- }
- } catch (MalformedURLException ex) {
- throw new IllegalArgumentException("The Azure Storage Blob endpoint url is malformed.");
- }
-
- SASTokenCredential credential = SASTokenCredential.fromQuery(url.getQuery());
- if (credential != null) {
- this.credential(credential);
- }
-
- return this;
- }
-
- /**
- * Sets the name of the container this client is connecting to.
- * @param containerName the name of the container
- * @return the updated BlockBlobClientBuilder object
- */
- public BlockBlobClientBuilder containerName(String containerName) {
- this.containerName = containerName;
- return this;
- }
-
- /**
- * Sets the name of the blob this client is connecting to.
- * @param blobName the name of the blob
- * @return the updated BlockBlobClientBuilder object
- */
- public BlockBlobClientBuilder blobName(String blobName) {
- this.blobName = blobName;
- return this;
- }
-
- /**
- * Sets the snapshot of the blob this client is connecting to.
- * @param snapshot the snapshot identifier for the blob
- * @return the updated BlockBlobClientBuilder object
- */
- public BlockBlobClientBuilder snapshot(String snapshot) {
- this.snapshot = snapshot;
- return this;
- }
-
- /**
- * Sets the credential used to authorize requests sent to the service
- * @param credential authorization credential
- * @return the updated BlockBlobClientBuilder object
- */
- public BlockBlobClientBuilder credential(SharedKeyCredential credential) {
- this.sharedKeyCredential = credential;
- this.tokenCredential = null;
- this.sasTokenCredential = null;
- return this;
- }
-
- /**
- * Sets the credential used to authorize requests sent to the service
- * @param credential authorization credential
- * @return the updated BlockBlobClientBuilder object
- */
- public BlockBlobClientBuilder credential(TokenCredential credential) {
- this.tokenCredential = credential;
- this.sharedKeyCredential = null;
- this.sasTokenCredential = null;
- return this;
- }
-
- /**
- * Sets the credential used to authorize requests sent to the service
- * @param credential authorization credential
- * @return the updated BlockBlobClientBuilder object
- */
- public BlockBlobClientBuilder credential(SASTokenCredential credential) {
- this.sasTokenCredential = credential;
- this.sharedKeyCredential = null;
- this.tokenCredential = null;
- return this;
- }
-
- /**
- * Clears the credential used to authorize requests sent to the service
- * @return the updated BlockBlobClientBuilder object
- */
- public BlockBlobClientBuilder anonymousCredential() {
- this.sharedKeyCredential = null;
- this.tokenCredential = null;
- this.sasTokenCredential = null;
- return this;
- }
-
- /**
- * Sets the connection string for the service, parses it for authentication information (account name, account key)
- * @param connectionString connection string from access keys section
- * @return the updated BlockBlobClientBuilder object
- * @throws IllegalArgumentException If {@code connectionString} doesn't contain AccountName or AccountKey
- */
- public BlockBlobClientBuilder connectionString(String connectionString) {
- Objects.requireNonNull(connectionString);
-
- Map connectionKVPs = new HashMap<>();
- for (String s : connectionString.split(";")) {
- String[] kvp = s.split("=", 2);
- connectionKVPs.put(kvp[0].toLowerCase(Locale.ROOT), kvp[1]);
- }
-
- String accountName = connectionKVPs.get(ACCOUNT_NAME);
- String accountKey = connectionKVPs.get(ACCOUNT_KEY);
- String endpointProtocol = connectionKVPs.get(ENDPOINT_PROTOCOL);
- String endpointSuffix = connectionKVPs.get(ENDPOINT_SUFFIX);
-
- if (ImplUtils.isNullOrEmpty(accountName) || ImplUtils.isNullOrEmpty(accountKey)) {
- throw new IllegalArgumentException("Connection string must contain 'AccountName' and 'AccountKey'.");
- }
-
- if (!ImplUtils.isNullOrEmpty(endpointProtocol) && !ImplUtils.isNullOrEmpty(endpointSuffix)) {
- String endpoint = String.format("%s://%s.blob.%s", endpointProtocol, accountName, endpointSuffix.replaceFirst("^\\.", ""));
- endpoint(endpoint);
- }
-
- // Use accountName and accountKey to get the SAS token using the credential class.
- return credential(new SharedKeyCredential(accountName, accountKey));
- }
-
- /**
- * Sets the http client used to send service requests
- * @param httpClient http client to send requests
- * @return the updated BlockBlobClientBuilder object
- */
- public BlockBlobClientBuilder httpClient(HttpClient httpClient) {
- this.httpClient = httpClient;
- return this;
- }
-
- /**
- * Adds a pipeline policy to apply on each request sent
- * @param pipelinePolicy a pipeline policy
- * @return the updated BlockBlobClientBuilder object
- */
- public BlockBlobClientBuilder addPolicy(HttpPipelinePolicy pipelinePolicy) {
- this.policies.add(pipelinePolicy);
- return this;
- }
-
- /**
- * Sets the logging level for service requests
- * @param logLevel logging level
- * @return the updated BlockBlobClientBuilder object
- */
- public BlockBlobClientBuilder httpLogDetailLevel(HttpLogDetailLevel logLevel) {
- this.logLevel = logLevel;
- return this;
- }
-
- /**
- * Sets the configuration object used to retrieve environment configuration values used to buildClient the client with
- * when they are not set in the appendBlobClientBuilder, defaults to Configuration.NONE
- * @param configuration configuration store
- * @return the updated BlockBlobClientBuilder object
- */
- public BlockBlobClientBuilder configuration(Configuration configuration) {
- this.configuration = configuration;
- return this;
- }
-
- /**
- * Sets the request retry options for all the requests made through the client.
- * @param retryOptions the options to configure retry behaviors
- * @return the updated BlockBlobClientBuilder object
- */
- public BlockBlobClientBuilder retryOptions(RequestRetryOptions retryOptions) {
- this.retryOptions = retryOptions;
- return this;
- }
-}
diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/Constants.java b/storage/client/blob/src/main/java/com/azure/storage/blob/Constants.java
index 653625b572c15..fa812df4b531b 100644
--- a/storage/client/blob/src/main/java/com/azure/storage/blob/Constants.java
+++ b/storage/client/blob/src/main/java/com/azure/storage/blob/Constants.java
@@ -288,6 +288,21 @@ static final class UrlConstants {
*/
public static final String SAS_SIGNED_KEY_VERSION = "skv";
+ /**
+ * The SAS blob constant.
+ */
+ public static final String SAS_BLOB_CONSTANT = "b";
+
+ /**
+ * The SAS blob snapshot constant.
+ */
+ public static final String SAS_BLOB_SNAPSHOT_CONSTANT = "bs";
+
+ /**
+ * The SAS blob snapshot constant.
+ */
+ public static final String SAS_CONTAINER_CONSTANT = "c";
+
private UrlConstants() {
// Private to prevent construction.
}
diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerAsyncClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerAsyncClient.java
index 406a7440b0c5b..936bab6932528 100644
--- a/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerAsyncClient.java
+++ b/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerAsyncClient.java
@@ -9,6 +9,7 @@
import com.azure.core.http.rest.VoidResponse;
import com.azure.core.util.Context;
import com.azure.storage.blob.implementation.AzureBlobStorageBuilder;
+import com.azure.storage.blob.implementation.AzureBlobStorageImpl;
import com.azure.storage.blob.models.BlobFlatListSegment;
import com.azure.storage.blob.models.BlobHierarchyListSegment;
import com.azure.storage.blob.models.BlobItem;
@@ -24,63 +25,68 @@
import com.azure.storage.blob.models.PublicAccessType;
import com.azure.storage.blob.models.SignedIdentifier;
import com.azure.storage.blob.models.StorageAccountInfo;
+import com.azure.storage.blob.models.UserDelegationKey;
+import com.azure.storage.common.credentials.SharedKeyCredential;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.net.MalformedURLException;
import java.net.URL;
import java.time.Duration;
+import java.time.OffsetDateTime;
+import java.time.temporal.ChronoUnit;
import java.util.List;
+import static com.azure.storage.blob.Utility.postProcessResponse;
+
/**
- * Client to a container. It may only be instantiated through a {@link ContainerClientBuilder} or via the method
- * {@link StorageAsyncClient#getContainerAsyncClient(String)}. This class does not hold any
- * state about a particular blob but is instead a convenient way of sending off appropriate requests to
- * the resource on the service. It may also be used to construct URLs to blobs.
+ * Client to a container. It may only be instantiated through a {@link ContainerClientBuilder} or via the method {@link
+ * StorageAsyncClient#getContainerAsyncClient(String)}. This class does not hold any state about a particular blob but
+ * is instead a convenient way of sending off appropriate requests to the resource on the service. It may also be used
+ * to construct URLs to blobs.
*
*
* This client contains operations on a container. Operations on a blob are available on {@link BlobAsyncClient} through
* {@link #getBlobAsyncClient(String)}, and operations on the service are available on {@link StorageAsyncClient}.
*
*
- * Please refer to the Azure Docs
- * for more information on containers.
+ * Please refer to the Azure
+ * Docs for more information on containers.
*
*
- * Note this client is an async client that returns reactive responses from Spring Reactor Core
- * project (https://projectreactor.io/). Calling the methods in this client will NOT
- * start the actual network operation, until {@code .subscribe()} is called on the reactive response.
- * You can simply convert one of these responses to a {@link java.util.concurrent.CompletableFuture}
- * object through {@link Mono#toFuture()}.
+ * Note this client is an async client that returns reactive responses from Spring Reactor Core project
+ * (https://projectreactor.io/). Calling the methods in this client will NOT start the actual network
+ * operation, until {@code .subscribe()} is called on the reactive response. You can simply convert one of these
+ * responses to a {@link java.util.concurrent.CompletableFuture} object through {@link Mono#toFuture()}.
*/
public final class ContainerAsyncClient {
- ContainerAsyncRawClient containerAsyncRawClient;
-
public static final String ROOT_CONTAINER_NAME = "$root";
public static final String STATIC_WEBSITE_CONTAINER_NAME = "$web";
public static final String LOG_CONTAINER_NAME = "$logs";
+ private final AzureBlobStorageImpl azureBlobStorage;
+
/**
* Package-private constructor for use by {@link ContainerClientBuilder}.
+ *
* @param azureBlobStorageBuilder the API client builder for blob storage API
*/
ContainerAsyncClient(AzureBlobStorageBuilder azureBlobStorageBuilder) {
- this.containerAsyncRawClient = new ContainerAsyncRawClient(azureBlobStorageBuilder.build());
+ this.azureBlobStorage = azureBlobStorageBuilder.build();
}
/**
* Creates a new {@link BlockBlobAsyncClient} object by concatenating the blobName to the end of
- * ContainerAsyncClient's URL. The new BlockBlobAsyncClient uses the same request policy pipeline as the ContainerAsyncClient.
- * To change the pipeline, create the BlockBlobAsyncClient and then call its WithPipeline method passing in the
- * desired pipeline object. Or, call this package's NewBlockBlobAsyncClient instead of calling this object's
- * NewBlockBlobAsyncClient method.
- *
- * @param blobName
- * A {@code String} representing the name of the blob.
- *
- * @return A new {@link BlockBlobAsyncClient} object which references the blob with the specified name in this container.
+ * ContainerAsyncClient's URL. The new BlockBlobAsyncClient uses the same request policy pipeline as the
+ * ContainerAsyncClient. To change the pipeline, create the BlockBlobAsyncClient and then call its WithPipeline
+ * method passing in the desired pipeline object. Or, call this package's NewBlockBlobAsyncClient instead of calling
+ * this object's NewBlockBlobAsyncClient method.
+ *
+ * @param blobName A {@code String} representing the name of the blob.
+ * @return A new {@link BlockBlobAsyncClient} object which references the blob with the specified name in this
+ * container.
*/
public BlockBlobAsyncClient getBlockBlobAsyncClient(String blobName) {
return getBlockBlobAsyncClient(blobName, null);
@@ -88,106 +94,95 @@ public BlockBlobAsyncClient getBlockBlobAsyncClient(String blobName) {
/**
* Creates a new {@link BlockBlobAsyncClient} object by concatenating the blobName to the end of
- * ContainerAsyncClient's URL. The new BlockBlobAsyncClient uses the same request policy pipeline as the ContainerAsyncClient.
- * To change the pipeline, create the BlockBlobAsyncClient and then call its WithPipeline method passing in the
- * desired pipeline object. Or, call this package's NewBlockBlobAsyncClient instead of calling this object's
- * NewBlockBlobAsyncClient method.
- *
- * @param blobName
- * A {@code String} representing the name of the blob.
- * @param snapshot
- * the snapshot identifier for the blob.
- *
- * @return A new {@link BlockBlobAsyncClient} object which references the blob with the specified name in this container.
+ * ContainerAsyncClient's URL. The new BlockBlobAsyncClient uses the same request policy pipeline as the
+ * ContainerAsyncClient. To change the pipeline, create the BlockBlobAsyncClient and then call its WithPipeline
+ * method passing in the desired pipeline object. Or, call this package's NewBlockBlobAsyncClient instead of calling
+ * this object's NewBlockBlobAsyncClient method.
+ *
+ * @param blobName A {@code String} representing the name of the blob.
+ * @param snapshot the snapshot identifier for the blob.
+ * @return A new {@link BlockBlobAsyncClient} object which references the blob with the specified name in this
+ * container.
*/
public BlockBlobAsyncClient getBlockBlobAsyncClient(String blobName, String snapshot) {
return new BlockBlobAsyncClient(new AzureBlobStorageBuilder()
.url(Utility.appendToURLPath(getContainerUrl(), blobName).toString())
- .pipeline(containerAsyncRawClient.azureBlobStorage.httpPipeline()), snapshot);
+ .pipeline(azureBlobStorage.httpPipeline()), snapshot);
}
/**
- * Creates creates a new PageBlobAsyncClient object by concatenating blobName to the end of
- * ContainerAsyncClient's URL. The new PageBlobAsyncClient uses the same request policy pipeline as the ContainerAsyncClient.
- * To change the pipeline, create the PageBlobAsyncClient and then call its WithPipeline method passing in the
- * desired pipeline object. Or, call this package's NewPageBlobAsyncClient instead of calling this object's
- * NewPageBlobAsyncClient method.
- *
- * @param blobName
- * A {@code String} representing the name of the blob.
- *
- * @return A new {@link PageBlobAsyncClient} object which references the blob with the specified name in this container.
+ * Creates creates a new PageBlobAsyncClient object by concatenating blobName to the end of ContainerAsyncClient's
+ * URL. The new PageBlobAsyncClient uses the same request policy pipeline as the ContainerAsyncClient. To change the
+ * pipeline, create the PageBlobAsyncClient and then call its WithPipeline method passing in the desired pipeline
+ * object. Or, call this package's NewPageBlobAsyncClient instead of calling this object's NewPageBlobAsyncClient
+ * method.
+ *
+ * @param blobName A {@code String} representing the name of the blob.
+ * @return A new {@link PageBlobAsyncClient} object which references the blob with the specified name in this
+ * container.
*/
public PageBlobAsyncClient getPageBlobAsyncClient(String blobName) {
return getPageBlobAsyncClient(blobName, null);
}
/**
- * Creates creates a new PageBlobAsyncClient object by concatenating blobName to the end of
- * ContainerAsyncClient's URL. The new PageBlobAsyncClient uses the same request policy pipeline as the ContainerAsyncClient.
- * To change the pipeline, create the PageBlobAsyncClient and then call its WithPipeline method passing in the
- * desired pipeline object. Or, call this package's NewPageBlobAsyncClient instead of calling this object's
- * NewPageBlobAsyncClient method.
- *
- * @param blobName
- * A {@code String} representing the name of the blob.
- * @param snapshot
- * the snapshot identifier for the blob.
- *
- * @return A new {@link PageBlobAsyncClient} object which references the blob with the specified name in this container.
+ * Creates creates a new PageBlobAsyncClient object by concatenating blobName to the end of ContainerAsyncClient's
+ * URL. The new PageBlobAsyncClient uses the same request policy pipeline as the ContainerAsyncClient. To change the
+ * pipeline, create the PageBlobAsyncClient and then call its WithPipeline method passing in the desired pipeline
+ * object. Or, call this package's NewPageBlobAsyncClient instead of calling this object's NewPageBlobAsyncClient
+ * method.
+ *
+ * @param blobName A {@code String} representing the name of the blob.
+ * @param snapshot the snapshot identifier for the blob.
+ * @return A new {@link PageBlobAsyncClient} object which references the blob with the specified name in this
+ * container.
*/
public PageBlobAsyncClient getPageBlobAsyncClient(String blobName, String snapshot) {
return new PageBlobAsyncClient(new AzureBlobStorageBuilder()
.url(Utility.appendToURLPath(getContainerUrl(), blobName).toString())
- .pipeline(containerAsyncRawClient.azureBlobStorage.httpPipeline()), snapshot);
+ .pipeline(azureBlobStorage.httpPipeline()), snapshot);
}
/**
- * Creates creates a new AppendBlobAsyncClient object by concatenating blobName to the end of
- * ContainerAsyncClient's URL. The new AppendBlobAsyncClient uses the same request policy pipeline as the ContainerAsyncClient.
- * To change the pipeline, create the AppendBlobAsyncClient and then call its WithPipeline method passing in the
- * desired pipeline object. Or, call this package's NewAppendBlobAsyncClient instead of calling this object's
+ * Creates creates a new AppendBlobAsyncClient object by concatenating blobName to the end of ContainerAsyncClient's
+ * URL. The new AppendBlobAsyncClient uses the same request policy pipeline as the ContainerAsyncClient. To change
+ * the pipeline, create the AppendBlobAsyncClient and then call its WithPipeline method passing in the desired
+ * pipeline object. Or, call this package's NewAppendBlobAsyncClient instead of calling this object's
* NewAppendBlobAsyncClient method.
*
- * @param blobName
- * A {@code String} representing the name of the blob.
- *
- * @return A new {@link AppendBlobAsyncClient} object which references the blob with the specified name in this container.
+ * @param blobName A {@code String} representing the name of the blob.
+ * @return A new {@link AppendBlobAsyncClient} object which references the blob with the specified name in this
+ * container.
*/
public AppendBlobAsyncClient getAppendBlobAsyncClient(String blobName) {
return getAppendBlobAsyncClient(blobName, null);
}
/**
- * Creates creates a new AppendBlobAsyncClient object by concatenating blobName to the end of
- * ContainerAsyncClient's URL. The new AppendBlobAsyncClient uses the same request policy pipeline as the ContainerAsyncClient.
- * To change the pipeline, create the AppendBlobAsyncClient and then call its WithPipeline method passing in the
- * desired pipeline object. Or, call this package's NewAppendBlobAsyncClient instead of calling this object's
+ * Creates creates a new AppendBlobAsyncClient object by concatenating blobName to the end of ContainerAsyncClient's
+ * URL. The new AppendBlobAsyncClient uses the same request policy pipeline as the ContainerAsyncClient. To change
+ * the pipeline, create the AppendBlobAsyncClient and then call its WithPipeline method passing in the desired
+ * pipeline object. Or, call this package's NewAppendBlobAsyncClient instead of calling this object's
* NewAppendBlobAsyncClient method.
*
- * @param blobName
- * A {@code String} representing the name of the blob.
- * @param snapshot
- * the snapshot identifier for the blob.
- *
- * @return A new {@link AppendBlobAsyncClient} object which references the blob with the specified name in this container.
+ * @param blobName A {@code String} representing the name of the blob.
+ * @param snapshot the snapshot identifier for the blob.
+ * @return A new {@link AppendBlobAsyncClient} object which references the blob with the specified name in this
+ * container.
*/
public AppendBlobAsyncClient getAppendBlobAsyncClient(String blobName, String snapshot) {
return new AppendBlobAsyncClient(new AzureBlobStorageBuilder()
.url(Utility.appendToURLPath(getContainerUrl(), blobName).toString())
- .pipeline(containerAsyncRawClient.azureBlobStorage.httpPipeline()), snapshot);
+ .pipeline(azureBlobStorage.httpPipeline()), snapshot);
}
/**
- * Creates a new BlobAsyncClient object by concatenating blobName to the end of
- * ContainerAsyncClient's URL. The new BlobAsyncClient uses the same request policy pipeline as the ContainerAsyncClient.
- * To change the pipeline, create the BlobAsyncClient and then call its WithPipeline method passing in the
- * desired pipeline object. Or, call this package's getBlobAsyncClient instead of calling this object's
- * getBlobAsyncClient method.
- *
- * @param blobName
- * A {@code String} representing the name of the blob.
+ * Creates a new BlobAsyncClient object by concatenating blobName to the end of ContainerAsyncClient's URL. The new
+ * BlobAsyncClient uses the same request policy pipeline as the ContainerAsyncClient. To change the pipeline, create
+ * the BlobAsyncClient and then call its WithPipeline method passing in the desired pipeline object. Or, call this
+ * package's getBlobAsyncClient instead of calling this object's getBlobAsyncClient method.
*
+ * @param blobName A {@code String} representing the name of the blob.
* @return A new {@link BlobAsyncClient} object which references the blob with the specified name in this container.
*/
public BlobAsyncClient getBlobAsyncClient(String blobName) {
@@ -195,55 +190,50 @@ public BlobAsyncClient getBlobAsyncClient(String blobName) {
}
/**
- * Creates a new BlobAsyncClient object by concatenating blobName to the end of
- * ContainerAsyncClient's URL. The new BlobAsyncClient uses the same request policy pipeline as the ContainerAsyncClient.
- * To change the pipeline, create the BlobAsyncClient and then call its WithPipeline method passing in the
- * desired pipeline object. Or, call this package's getBlobAsyncClient instead of calling this object's
- * getBlobAsyncClient method.
- *
- * @param blobName
- * A {@code String} representing the name of the blob.
- * @param snapshot
- * the snapshot identifier for the blob.
+ * Creates a new BlobAsyncClient object by concatenating blobName to the end of ContainerAsyncClient's URL. The new
+ * BlobAsyncClient uses the same request policy pipeline as the ContainerAsyncClient. To change the pipeline, create
+ * the BlobAsyncClient and then call its WithPipeline method passing in the desired pipeline object. Or, call this
+ * package's getBlobAsyncClient instead of calling this object's getBlobAsyncClient method.
*
+ * @param blobName A {@code String} representing the name of the blob.
+ * @param snapshot the snapshot identifier for the blob.
* @return A new {@link BlobAsyncClient} object which references the blob with the specified name in this container.
*/
public BlobAsyncClient getBlobAsyncClient(String blobName, String snapshot) {
return new BlobAsyncClient(new AzureBlobStorageBuilder()
.url(Utility.appendToURLPath(getContainerUrl(), blobName).toString())
- .pipeline(containerAsyncRawClient.azureBlobStorage.httpPipeline()), snapshot);
+ .pipeline(azureBlobStorage.httpPipeline()), snapshot);
}
/**
* Initializes a {@link StorageAsyncClient} object pointing to the storage account this container is in.
*
- * @return
- * A {@link StorageAsyncClient} object pointing to the specified storage account
+ * @return A {@link StorageAsyncClient} object pointing to the specified storage account
*/
public StorageAsyncClient getStorageAsyncClient() {
return new StorageAsyncClient(new AzureBlobStorageBuilder()
.url(Utility.stripLastPathSegment(getContainerUrl()).toString())
- .pipeline(containerAsyncRawClient.azureBlobStorage.httpPipeline()));
+ .pipeline(azureBlobStorage.httpPipeline()));
}
/**
* Gets the URL of the container represented by this client.
+ *
* @return the URL.
* @throws RuntimeException If the container has a malformed URL.
*/
public URL getContainerUrl() {
try {
- return new URL(containerAsyncRawClient.azureBlobStorage.url());
+ return new URL(azureBlobStorage.url());
} catch (MalformedURLException e) {
- throw new RuntimeException(String.format("Invalid URL on %s: %s" + getClass().getSimpleName(), containerAsyncRawClient.azureBlobStorage.url()), e);
+ throw new RuntimeException(String.format("Invalid URL on %s: %s" + getClass().getSimpleName(), azureBlobStorage.url()), e);
}
}
/**
* Gets if the container this client represents exists in the cloud.
*
- * @return
- * true if the container exists, false if it doesn't
+ * @return true if the container exists, false if it doesn't
*/
public Mono> exists() {
return this.getProperties(null)
@@ -259,8 +249,7 @@ public Mono> exists() {
* fails. For more information, see the
* Azure Docs.
*
- * @return
- * A reactive response signalling completion.
+ * @return A reactive response signalling completion.
*/
public Mono create() {
return this.create(null, null);
@@ -271,47 +260,52 @@ public Mono create() {
* fails. For more information, see the
* Azure Docs.
*
- * @param metadata
- * {@link Metadata}
- * @param accessType
- * Specifies how the data in this container is available to the public. See the x-ms-blob-public-access header
- * in the Azure Docs for more information. Pass null for no public access.
- *
- * @return
- * A reactive response signalling completion.
+ * @param metadata {@link Metadata}
+ * @param accessType Specifies how the data in this container is available to the public. See the
+ * x-ms-blob-public-access header in the Azure Docs for more information. Pass null for no public access.
+ * @return A reactive response signalling completion.
*/
public Mono create(Metadata metadata, PublicAccessType accessType) {
- return containerAsyncRawClient
- .create(metadata, accessType)
+ metadata = metadata == null ? new Metadata() : metadata;
+
+ return postProcessResponse(this.azureBlobStorage.containers().createWithRestResponseAsync(
+ null, null, metadata, accessType, null, Context.NONE))
.map(VoidResponse::new);
}
/**
- * Marks the specified container for deletion. The container and any blobs contained within it are later
- * deleted during garbage collection. For more information, see the
+ * Marks the specified container for deletion. The container and any blobs contained within it are later deleted
+ * during garbage collection. For more information, see the
* Azure Docs.
*
- * @return
- * A reactive response signalling completion.
+ * @return A reactive response signalling completion.
*/
public Mono delete() {
return this.delete(null);
}
/**
- * Marks the specified container for deletion. The container and any blobs contained within it are later
- * deleted during garbage collection. For more information, see the
+ * Marks the specified container for deletion. The container and any blobs contained within it are later deleted
+ * during garbage collection. For more information, see the
* Azure Docs.
*
- * @param accessConditions
- * {@link ContainerAccessConditions}
- *
- * @return
- * A reactive response signalling completion.
+ * @param accessConditions {@link ContainerAccessConditions}
+ * @return A reactive response signalling completion.
+ * @throws UnsupportedOperationException If {@link ContainerAccessConditions#modifiedAccessConditions()} has either
+ * {@link ModifiedAccessConditions#ifMatch()} or {@link ModifiedAccessConditions#ifNoneMatch()} set.
*/
public Mono delete(ContainerAccessConditions accessConditions) {
- return containerAsyncRawClient
- .delete(accessConditions)
+ accessConditions = accessConditions == null ? new ContainerAccessConditions() : accessConditions;
+
+ if (!validateNoEtag(accessConditions.modifiedAccessConditions())) {
+ // Throwing is preferred to Single.error because this will error out immediately instead of waiting until
+ // subscription.
+ throw new UnsupportedOperationException("ETag access conditions are not supported for this API.");
+ }
+
+ return postProcessResponse(this.azureBlobStorage.containers()
+ .deleteWithRestResponseAsync(null, null, null,
+ accessConditions.leaseAccessConditions(), accessConditions.modifiedAccessConditions(), Context.NONE))
.map(VoidResponse::new);
}
@@ -319,8 +313,7 @@ public Mono delete(ContainerAccessConditions accessConditions) {
* Returns the container's metadata and system properties. For more information, see the
* Azure Docs.
*
- * @return
- * A reactive response containing the container properties.
+ * @return A reactive response containing the container properties.
*/
public Mono> getProperties() {
return this.getProperties(null);
@@ -330,16 +323,14 @@ public Mono> getProperties() {
* Returns the container's metadata and system properties. For more information, see the
*