All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.azure.storage.blob.BlobServiceAsyncClient Maven / Gradle / Ivy

There is a newer version: 12.29.0
Show newest version
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.azure.storage.blob;

import com.azure.core.annotation.ReturnType;
import com.azure.core.annotation.ServiceClient;
import com.azure.core.annotation.ServiceMethod;
import com.azure.core.credential.TokenCredential;
import com.azure.core.http.HttpPipeline;
import com.azure.core.http.HttpResponse;
import com.azure.core.http.rest.PagedFlux;
import com.azure.core.http.rest.PagedResponse;
import com.azure.core.http.rest.PagedResponseBase;
import com.azure.core.http.rest.Response;
import com.azure.core.http.rest.SimpleResponse;
import com.azure.core.util.Context;
import com.azure.core.util.CoreUtils;
import com.azure.core.util.FluxUtil;
import com.azure.core.util.logging.ClientLogger;
import com.azure.storage.blob.implementation.AzureBlobStorageImpl;
import com.azure.storage.blob.implementation.AzureBlobStorageImplBuilder;
import com.azure.storage.blob.implementation.models.EncryptionScope;
import com.azure.storage.blob.implementation.models.ServicesGetAccountInfoHeaders;
import com.azure.storage.blob.implementation.util.ModelHelper;
import com.azure.storage.blob.models.BlobContainerEncryptionScope;
import com.azure.storage.blob.models.BlobContainerItem;
import com.azure.storage.blob.models.BlobContainerListDetails;
import com.azure.storage.blob.models.BlobCorsRule;
import com.azure.storage.blob.models.BlobRetentionPolicy;
import com.azure.storage.blob.models.BlobServiceProperties;
import com.azure.storage.blob.models.BlobServiceStatistics;
import com.azure.storage.blob.models.BlobStorageException;
import com.azure.storage.blob.models.CpkInfo;
import com.azure.storage.blob.models.KeyInfo;
import com.azure.storage.blob.models.ListBlobContainersIncludeType;
import com.azure.storage.blob.models.ListBlobContainersOptions;
import com.azure.storage.blob.models.PublicAccessType;
import com.azure.storage.blob.models.StorageAccountInfo;
import com.azure.storage.blob.models.TaggedBlobItem;
import com.azure.storage.blob.models.UserDelegationKey;
import com.azure.storage.blob.options.BlobContainerCreateOptions;
import com.azure.storage.blob.options.FindBlobsOptions;
import com.azure.storage.blob.options.UndeleteBlobContainerOptions;
import com.azure.storage.common.StorageSharedKeyCredential;
import com.azure.storage.common.implementation.AccountSasImplUtil;
import com.azure.storage.common.implementation.Constants;
import com.azure.storage.common.implementation.SasImplUtils;
import com.azure.storage.common.implementation.StorageImplUtils;
import com.azure.storage.common.sas.AccountSasSignatureValues;
import reactor.core.publisher.Mono;

import java.net.URI;
import java.time.Duration;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.stream.Collectors;

import static com.azure.core.util.FluxUtil.monoError;
import static com.azure.core.util.FluxUtil.pagedFluxError;
import static com.azure.core.util.FluxUtil.withContext;

/**
 * Client to a storage account. It may only be instantiated through a {@link BlobServiceClientBuilder}. This class does
 * not hold any state about a particular storage account 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 and containers.
 *
 * 

* This client contains operations on a blob. Operations on a container are available on {@link * BlobContainerAsyncClient} through {@link #getBlobContainerAsyncClient(String)}, and operations on a blob are * available on {@link BlobAsyncClient}. * *

* Please see 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()}. */ @ServiceClient(builder = BlobServiceClientBuilder.class, isAsync = true) public final class BlobServiceAsyncClient { private static final ClientLogger LOGGER = new ClientLogger(BlobServiceAsyncClient.class); private final AzureBlobStorageImpl azureBlobStorage; private final String accountName; private final BlobServiceVersion serviceVersion; private final CpkInfo customerProvidedKey; // only used to pass down to blob clients private final EncryptionScope encryptionScope; // only used to pass down to blob clients private final BlobContainerEncryptionScope blobContainerEncryptionScope; // only used to pass down to container // clients private final boolean anonymousAccess; /** * Package-private constructor for use by {@link BlobServiceClientBuilder}. * * @param pipeline The pipeline used to send and receive service requests. * @param url The endpoint where to send service requests. * @param serviceVersion The version of the service to receive requests. * @param accountName The storage account name. * @param customerProvidedKey Customer provided key used during encryption of the blob's data on the server, pass * {@code null} to allow the service to use its own encryption. * @param encryptionScope Encryption scope used during encryption of the blob's data on the server, pass * {@code null} to allow the service to use its own encryption. * @param anonymousAccess Whether the client was built with anonymousAccess */ BlobServiceAsyncClient(HttpPipeline pipeline, String url, BlobServiceVersion serviceVersion, String accountName, CpkInfo customerProvidedKey, EncryptionScope encryptionScope, BlobContainerEncryptionScope blobContainerEncryptionScope, boolean anonymousAccess) { /* Check to make sure the uri is valid. We don't want the error to occur later in the generated layer when the sas token has already been applied. */ try { URI.create(url); } catch (IllegalArgumentException ex) { throw LOGGER.logExceptionAsError(ex); } this.azureBlobStorage = new AzureBlobStorageImplBuilder() .pipeline(pipeline) .url(url) .version(serviceVersion.getVersion()) .buildClient(); this.serviceVersion = serviceVersion; this.accountName = accountName; this.customerProvidedKey = customerProvidedKey; this.encryptionScope = encryptionScope; this.blobContainerEncryptionScope = blobContainerEncryptionScope; this.anonymousAccess = anonymousAccess; } /** * Initializes a {@link BlobContainerAsyncClient} object pointing to the specified container. This method does not * create a container. It simply constructs the URL to the container and offers access to methods relevant to * containers. * *

Code Samples

* * *
     * BlobContainerAsyncClient blobContainerAsyncClient = client.getBlobContainerAsyncClient("containerName");
     * 
* * * @param containerName The name of the container to point to. A value of null or empty string will be interpreted * as pointing to the root container and will be replaced by "$root". * @return A {@link BlobContainerAsyncClient} object pointing to the specified container */ public BlobContainerAsyncClient getBlobContainerAsyncClient(String containerName) { if (CoreUtils.isNullOrEmpty(containerName)) { containerName = BlobContainerAsyncClient.ROOT_CONTAINER_NAME; } return new BlobContainerAsyncClient(getHttpPipeline(), getAccountUrl(), getServiceVersion(), getAccountName(), containerName, customerProvidedKey, encryptionScope, blobContainerEncryptionScope); } /** * Gets the {@link HttpPipeline} powering this client. * * @return The pipeline. */ public HttpPipeline getHttpPipeline() { return azureBlobStorage.getHttpPipeline(); } /** * Gets the service version the client is using. * * @return the service version the client is using. */ public BlobServiceVersion getServiceVersion() { return serviceVersion; } /** * Creates a new container within a storage account. If a container with the same name already exists, the operation * fails. For more information, see the * Azure Docs. * *

Code Samples

* * *
     * BlobContainerAsyncClient blobContainerAsyncClient =
     *     client.createBlobContainer("containerName").block();
     * 
* * * @param containerName Name of the container to create * @return A {@link Mono} containing a {@link BlobContainerAsyncClient} used to interact with the container created. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono createBlobContainer(String containerName) { return createBlobContainerWithResponse(containerName, null, null).flatMap(FluxUtil::toMono); } /** * Creates a new container within a storage account. If a container with the same name already exists, the operation * fails. For more information, see the * Azure Docs. * *

Code Samples

* * *
     * Map<String, String> metadata = Collections.singletonMap("metadata", "value");
     *
     * BlobContainerAsyncClient containerClient = client
     *     .createBlobContainerWithResponse("containerName", metadata, PublicAccessType.CONTAINER).block().getValue();
     * 
* * * @param containerName Name of the container to create * @param metadata Metadata to associate with the container. If there is leading or trailing whitespace in any * metadata key or value, it must be removed or encoded. * @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 {@link Mono} containing a {@link Response} whose {@link Response#getValue() value} contains a {@link * BlobContainerAsyncClient} used to interact with the container created. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono> createBlobContainerWithResponse(String containerName, Map metadata, PublicAccessType accessType) { try { return withContext(context -> createBlobContainerWithResponse(containerName, metadata, accessType, context)); } catch (RuntimeException ex) { return monoError(LOGGER, ex); } } Mono> createBlobContainerWithResponse(String containerName, Map metadata, PublicAccessType accessType, Context context) { throwOnAnonymousAccess(); BlobContainerAsyncClient blobContainerAsyncClient = getBlobContainerAsyncClient(containerName); return blobContainerAsyncClient.createWithResponse(metadata, accessType, context) .map(response -> new SimpleResponse<>(response, blobContainerAsyncClient)); } /** * Creates a new container within a storage account if it does not exist. For more information, see the * Azure Docs. * *

Code Samples

* * *
     * BlobContainerAsyncClient blobContainerAsyncClient =
     *     client.createBlobContainerIfNotExists("containerName").block();
     * 
* * * @param containerName Name of the container to create * @return A {@link Mono} containing a {@link BlobContainerAsyncClient} used to interact with the container created. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono createBlobContainerIfNotExists(String containerName) { return createBlobContainerIfNotExistsWithResponse(containerName, null, null).flatMap(FluxUtil::toMono); } /** * Creates a new container within a storage account if it does not exist. For more information, see the * Azure Docs. * *

Code Samples

* * *
     * Map<String, String> metadata = Collections.singletonMap("metadata", "value");
     * BlobContainerCreateOptions options = new BlobContainerCreateOptions().setMetadata(metadata)
     *     .setPublicAccessType(PublicAccessType.CONTAINER);
     *
     * client.createBlobContainerIfNotExistsWithResponse("containerName", options).subscribe(response -> {
     *     if (response.getStatusCode() == 409) {
     *         System.out.println("Already exists.");
     *     } else {
     *         System.out.println("successfully created.");
     *     }
     * });
     * 
* * * @param containerName Name of the container to create * @param options {@link BlobContainerCreateOptions} * @return A {@link Mono} containing a {@link Response} whose {@link Response#getValue() value} contains a {@link * BlobContainerAsyncClient} used to interact with the container created. If {@link Response}'s status code is 201, * a new container was successfully created. If status code is 409, a container with the same name already existed * at this location. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono> createBlobContainerIfNotExistsWithResponse(String containerName, BlobContainerCreateOptions options) { try { return withContext(context -> createBlobContainerIfNotExistsWithResponse(containerName, options, context)); } catch (RuntimeException ex) { return monoError(LOGGER, ex); } } Mono> createBlobContainerIfNotExistsWithResponse(String containerName, BlobContainerCreateOptions options, Context context) { try { options = options == null ? new BlobContainerCreateOptions() : options; return createBlobContainerWithResponse(containerName, options.getMetadata(), options.getPublicAccessType(), context).onErrorResume(t -> t instanceof BlobStorageException && ((BlobStorageException) t) .getStatusCode() == 409, t -> { HttpResponse response = ((BlobStorageException) t).getResponse(); return Mono.just(new SimpleResponse<>(response.getRequest(), response.getStatusCode(), response.getHeaders(), this.getBlobContainerAsyncClient(containerName))); }); } catch (RuntimeException ex) { return monoError(LOGGER, ex); } } /** * Deletes the specified container in the storage account. If the container doesn't exist the operation fails. For * more information see the Azure Docs. *

Code Samples

* * *
     * client.deleteBlobContainer("containerName").subscribe(
     *     response -> System.out.printf("Delete container completed%n"),
     *     error -> System.out.printf("Delete container failed: %s%n", error));
     * 
* * * @param containerName Name of the container to delete * @return A {@link Mono} containing status code and HTTP headers */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono deleteBlobContainer(String containerName) { return deleteBlobContainerWithResponse(containerName).flatMap(FluxUtil::toMono); } /** * Deletes the specified container in the storage account. If the container doesn't exist the operation fails. For * more information see the Azure * Docs. * *

Code Samples

* * *
     * Context context = new Context("Key", "Value");
     * client.deleteBlobContainerWithResponse("containerName").subscribe(response ->
     *     System.out.printf("Delete container completed with status %d%n", response.getStatusCode()));
     * 
* * * @param containerName Name of the container to delete * @return A {@link Mono} containing status code and HTTP headers */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono> deleteBlobContainerWithResponse(String containerName) { try { return withContext(context -> deleteBlobContainerWithResponse(containerName, context)); } catch (RuntimeException ex) { return monoError(LOGGER, ex); } } Mono> deleteBlobContainerWithResponse(String containerName, Context context) { throwOnAnonymousAccess(); return getBlobContainerAsyncClient(containerName).deleteWithResponse(null, context); } /** * Deletes the specified container in the storage account if it exists. For * more information see the Azure * Docs. *

Code Samples

* * *
     * client.deleteBlobContainerIfExists("containerName").subscribe(deleted -> {
     *     if (deleted) {
     *         System.out.println("Successfully deleted.");
     *     } else {
     *         System.out.println("Does not exist.");
     *     }
     * });
     * 
* * * @param containerName Name of the container to delete * @return A reactive {@link Mono} signaling completion. {@code true} indicates that the container was deleted. * {@code false} indicates the container does not exist at this location. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono deleteBlobContainerIfExists(String containerName) { return deleteBlobContainerIfExistsWithResponse(containerName).flatMap(FluxUtil::toMono); } /** * Deletes the specified container in the storage account if it exists. * For more information see the Azure * Docs. * *

Code Samples

* * *
     * Context context = new Context("Key", "Value");
     * client.deleteBlobContainerIfExistsWithResponse("containerName").subscribe(response -> {
     *     if (response.getStatusCode() == 404) {
     *         System.out.println("Does not exist.");
     *     } else {
     *         System.out.println("successfully deleted.");
     *     }
     * });
     * 
* * * @param containerName Name of the container to delete * @return A reactive response signaling completion. If {@link Response}'s status code is 202, the blob container was * successfully deleted. If status code is 404, the blob container does not exist. * */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono> deleteBlobContainerIfExistsWithResponse(String containerName) { try { return withContext(context -> deleteBlobContainerIfExistsWithResponse(containerName, context)); } catch (RuntimeException ex) { return monoError(LOGGER, ex); } } Mono> deleteBlobContainerIfExistsWithResponse(String containerName, Context context) { try { return deleteBlobContainerWithResponse(containerName, context) .map(response -> (Response) new SimpleResponse<>(response, true)) .onErrorResume(t -> t instanceof BlobStorageException && ((BlobStorageException) t).getStatusCode() == 404, t -> { HttpResponse response = ((BlobStorageException) t).getResponse(); return Mono.just(new SimpleResponse<>(response.getRequest(), response.getStatusCode(), response.getHeaders(), false)); }); } catch (RuntimeException ex) { return monoError(LOGGER, ex); } } /** * Gets the URL of the storage account represented by this client. * * @return the URL. */ public String getAccountUrl() { return azureBlobStorage.getUrl(); } /** * Returns a reactive Publisher emitting all the containers in this account lazily as needed. For more information, * see the Azure Docs. * *

Code Samples

* * *
     * client.listBlobContainers().subscribe(container -> System.out.printf("Name: %s%n", container.getName()));
     * 
* * * @return A reactive response emitting the list of containers. */ @ServiceMethod(returns = ReturnType.COLLECTION) public PagedFlux listBlobContainers() { return this.listBlobContainers(new ListBlobContainersOptions()); } /** * Returns a reactive Publisher emitting all the containers in this account lazily as needed. For more information, * see the Azure Docs. * *

Code Samples

* * *
     * ListBlobContainersOptions options = new ListBlobContainersOptions()
     *     .setPrefix("containerNamePrefixToMatch")
     *     .setDetails(new BlobContainerListDetails().setRetrieveMetadata(true));
     *
     * client.listBlobContainers(options).subscribe(container -> System.out.printf("Name: %s%n", container.getName()));
     * 
* * * @param options A {@link ListBlobContainersOptions} which specifies what data should be returned by the service. * @return A reactive response emitting the list of containers. */ @ServiceMethod(returns = ReturnType.COLLECTION) public PagedFlux listBlobContainers(ListBlobContainersOptions options) { try { return listBlobContainersWithOptionalTimeout(options, null); } catch (RuntimeException ex) { return pagedFluxError(LOGGER, ex); } } PagedFlux listBlobContainersWithOptionalTimeout(ListBlobContainersOptions options, Duration timeout) { throwOnAnonymousAccess(); BiFunction>> func = (marker, pageSize) -> { ListBlobContainersOptions finalOptions; if (pageSize != null) { if (options == null) { finalOptions = new ListBlobContainersOptions().setMaxResultsPerPage(pageSize); } else { finalOptions = new ListBlobContainersOptions() .setMaxResultsPerPage(pageSize) .setDetails(options.getDetails()) .setPrefix(options.getPrefix()); } } else { finalOptions = options; } return listBlobContainersSegment(marker, finalOptions, timeout); }; return new PagedFlux<>(pageSize -> func.apply(null, pageSize), func); } private Mono> listBlobContainersSegment(String marker, ListBlobContainersOptions options, Duration timeout) { options = options == null ? new ListBlobContainersOptions() : options; return StorageImplUtils.applyOptionalTimeout( this.azureBlobStorage.getServices().listBlobContainersSegmentSinglePageAsync( options.getPrefix(), marker, options.getMaxResultsPerPage(), toIncludeTypes(options.getDetails()), null, null, Context.NONE), timeout); } /** * Returns a reactive Publisher emitting the blobs in this account whose tags match the query expression. For more * information, including information on the query syntax, see the Azure Docs. * *

Code Samples

* * *
     * client.findBlobsByTags("where=tag=value").subscribe(blob -> System.out.printf("Name: %s%n", blob.getName()));
     * 
* * * @param query Filters the results to return only blobs whose tags match the specified expression. * @return A reactive response emitting the list of blobs. */ @ServiceMethod(returns = ReturnType.COLLECTION) public PagedFlux findBlobsByTags(String query) { return this.findBlobsByTags(new FindBlobsOptions(query)); } /** * Returns a reactive Publisher emitting the blobs in this account whose tags match the query expression. For more * information, including information on the query syntax, see the Azure Docs. * *

Code Samples

* * *
     * client.findBlobsByTags(new FindBlobsOptions("where=tag=value").setMaxResultsPerPage(10))
     *     .subscribe(blob -> System.out.printf("Name: %s%n", blob.getName()));
     * 
* * * @param options {@link FindBlobsOptions} * @return A reactive response emitting the list of blobs. */ @ServiceMethod(returns = ReturnType.COLLECTION) public PagedFlux findBlobsByTags(FindBlobsOptions options) { try { return findBlobsByTags(options, null, Context.NONE); } catch (RuntimeException ex) { return pagedFluxError(LOGGER, ex); } } PagedFlux findBlobsByTags(FindBlobsOptions options, Duration timeout, Context context) { throwOnAnonymousAccess(); StorageImplUtils.assertNotNull("options", options); BiFunction>> func = (marker, pageSize) -> { FindBlobsOptions finalOptions; if (pageSize != null) { finalOptions = new FindBlobsOptions(options.getQuery()) .setMaxResultsPerPage(pageSize); } else { finalOptions = options; } return this.findBlobsByTags(finalOptions, marker, timeout, context); }; return new PagedFlux<>(pageSize -> func.apply(null, pageSize), func); } private Mono> findBlobsByTags( FindBlobsOptions options, String marker, Duration timeout, Context context) { throwOnAnonymousAccess(); StorageImplUtils.assertNotNull("options", options); return StorageImplUtils.applyOptionalTimeout( this.azureBlobStorage.getServices().filterBlobsWithResponseAsync(null, null, options.getQuery(), marker, options.getMaxResultsPerPage(), null, context), timeout) .map(response -> { List value = response.getValue().getBlobs() == null ? Collections.emptyList() : response.getValue().getBlobs().stream() .map(ModelHelper::populateTaggedBlobItem) .collect(Collectors.toList()); return new PagedResponseBase<>( response.getRequest(), response.getStatusCode(), response.getHeaders(), value, response.getValue().getNextMarker(), response.getDeserializedHeaders()); }); } /** * Converts {@link BlobContainerListDetails} into list of {@link ListBlobContainersIncludeType} * that contains only options selected. If no option is selected then null is returned. * * @return a list of selected options converted into {@link ListBlobContainersIncludeType}, null if none * of options has been selected. */ private List toIncludeTypes(BlobContainerListDetails blobContainerListDetails) { boolean hasDetails = blobContainerListDetails != null && (blobContainerListDetails.getRetrieveMetadata() || blobContainerListDetails.getRetrieveDeleted() || blobContainerListDetails.getRetrieveSystemContainers()); if (hasDetails) { List flags = new ArrayList<>(3); if (blobContainerListDetails.getRetrieveDeleted()) { flags.add(ListBlobContainersIncludeType.DELETED); } if (blobContainerListDetails.getRetrieveMetadata()) { flags.add(ListBlobContainersIncludeType.METADATA); } if (blobContainerListDetails.getRetrieveSystemContainers()) { flags.add(ListBlobContainersIncludeType.SYSTEM); } return flags; } else { return null; } } /** * Gets the properties of a storage account’s Blob service. For more information, see the * Azure Docs. * *

Code Samples

* * *
     * client.getProperties().subscribe(response ->
     *     System.out.printf("Hour metrics enabled: %b, Minute metrics enabled: %b%n",
     *         response.getHourMetrics().isEnabled(),
     *         response.getMinuteMetrics().isEnabled()));
     * 
* * * @return A reactive response containing the storage account properties. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono getProperties() { return getPropertiesWithResponse().flatMap(FluxUtil::toMono); } /** * Gets the properties of a storage account’s Blob service. For more information, see the * Azure Docs. * *

Code Samples

* * *
     * client.getPropertiesWithResponse().subscribe(response ->
     *     System.out.printf("Hour metrics enabled: %b, Minute metrics enabled: %b%n",
     *         response.getValue().getHourMetrics().isEnabled(),
     *         response.getValue().getMinuteMetrics().isEnabled()));
     * 
* * * @return A {@link Mono} containing a {@link Response} whose {@link Response#getValue() value} contains the storage * account properties. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono> getPropertiesWithResponse() { try { return withContext(this::getPropertiesWithResponse); } catch (RuntimeException ex) { return monoError(LOGGER, ex); } } Mono> getPropertiesWithResponse(Context context) { context = context == null ? Context.NONE : context; throwOnAnonymousAccess(); return this.azureBlobStorage.getServices().getPropertiesWithResponseAsync(null, null, context) .map(rb -> new SimpleResponse<>(rb, rb.getValue())); } /** * Sets properties for a storage account's Blob service endpoint. For more information, see the * Azure Docs. * Note that setting the default service version has no effect when using this client because this client explicitly * sets the version header on each request, overriding the default. *

This method checks to ensure the properties being sent follow the specifications indicated in the Azure Docs. * If CORS policies are set, CORS parameters that are not set default to the empty string.

* *

Code Samples

* * *
     * BlobRetentionPolicy loggingRetentionPolicy = new BlobRetentionPolicy().setEnabled(true).setDays(3);
     * BlobRetentionPolicy metricsRetentionPolicy = new BlobRetentionPolicy().setEnabled(true).setDays(1);
     *
     * BlobServiceProperties properties = new BlobServiceProperties()
     *     .setLogging(new BlobAnalyticsLogging()
     *         .setWrite(true)
     *         .setDelete(true)
     *         .setRetentionPolicy(loggingRetentionPolicy))
     *     .setHourMetrics(new BlobMetrics()
     *         .setEnabled(true)
     *         .setRetentionPolicy(metricsRetentionPolicy))
     *     .setMinuteMetrics(new BlobMetrics()
     *         .setEnabled(true)
     *         .setRetentionPolicy(metricsRetentionPolicy));
     *
     * client.setProperties(properties).subscribe(
     *     response -> System.out.printf("Setting properties completed%n"),
     *     error -> System.out.printf("Setting properties failed: %s%n", error));
     * 
* * * @param properties Configures the service. * @return A {@link Mono} containing the storage account properties. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono setProperties(BlobServiceProperties properties) { return setPropertiesWithResponse(properties).flatMap(FluxUtil::toMono); } /** * Sets properties for a storage account's Blob service endpoint. For more information, see the * Azure Docs. * Note that setting the default service version has no effect when using this client because this client explicitly * sets the version header on each request, overriding the default. *

This method checks to ensure the properties being sent follow the specifications indicated in the Azure Docs. * If CORS policies are set, CORS parameters that are not set default to the empty string.

*

Code Samples

* * *
     * BlobRetentionPolicy loggingRetentionPolicy = new BlobRetentionPolicy().setEnabled(true).setDays(3);
     * BlobRetentionPolicy metricsRetentionPolicy = new BlobRetentionPolicy().setEnabled(true).setDays(1);
     *
     * BlobServiceProperties properties = new BlobServiceProperties()
     *     .setLogging(new BlobAnalyticsLogging()
     *         .setWrite(true)
     *         .setDelete(true)
     *         .setRetentionPolicy(loggingRetentionPolicy))
     *     .setHourMetrics(new BlobMetrics()
     *         .setEnabled(true)
     *         .setRetentionPolicy(metricsRetentionPolicy))
     *     .setMinuteMetrics(new BlobMetrics()
     *         .setEnabled(true)
     *         .setRetentionPolicy(metricsRetentionPolicy));
     *
     * client.setPropertiesWithResponse(properties).subscribe(response ->
     *     System.out.printf("Setting properties completed with status %d%n", response.getStatusCode()));
     * 
* * * @param properties Configures the service. * @return A {@link Mono} containing the storage account properties. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono> setPropertiesWithResponse(BlobServiceProperties properties) { try { return withContext(context -> setPropertiesWithResponse(properties, context)); } catch (RuntimeException ex) { return monoError(LOGGER, ex); } } Mono> setPropertiesWithResponse(BlobServiceProperties properties, Context context) { throwOnAnonymousAccess(); BlobServiceProperties finalProperties = null; if (properties != null) { finalProperties = new BlobServiceProperties(); // Logging finalProperties.setLogging(properties.getLogging()); if (finalProperties.getLogging() != null) { StorageImplUtils.assertNotNull("Logging Version", finalProperties.getLogging().getVersion()); validateRetentionPolicy(finalProperties.getLogging().getRetentionPolicy(), "Logging Retention Policy"); } // Hour Metrics finalProperties.setHourMetrics(properties.getHourMetrics()); if (finalProperties.getHourMetrics() != null) { StorageImplUtils.assertNotNull("HourMetrics Version", finalProperties.getHourMetrics().getVersion()); validateRetentionPolicy(finalProperties.getHourMetrics().getRetentionPolicy(), "HourMetrics Retention " + "Policy"); if (finalProperties.getHourMetrics().isEnabled()) { StorageImplUtils.assertNotNull("HourMetrics IncludeApis", finalProperties.getHourMetrics().isIncludeApis()); } } // Minute Metrics finalProperties.setMinuteMetrics(properties.getMinuteMetrics()); if (finalProperties.getMinuteMetrics() != null) { StorageImplUtils.assertNotNull("MinuteMetrics Version", finalProperties.getMinuteMetrics().getVersion()); validateRetentionPolicy(finalProperties.getMinuteMetrics().getRetentionPolicy(), "MinuteMetrics " + "Retention Policy"); if (finalProperties.getMinuteMetrics().isEnabled()) { StorageImplUtils.assertNotNull("MinuteMetrics IncludeApis", finalProperties.getHourMetrics().isIncludeApis()); } } // CORS if (properties.getCors() != null) { List corsRules = new ArrayList<>(); for (BlobCorsRule rule : properties.getCors()) { corsRules.add(validatedCorsRule(rule)); } finalProperties.setCors(corsRules); } // Default Service Version finalProperties.setDefaultServiceVersion(properties.getDefaultServiceVersion()); // Delete Retention Policy finalProperties.setDeleteRetentionPolicy(properties.getDeleteRetentionPolicy()); validateRetentionPolicy(finalProperties.getDeleteRetentionPolicy(), "DeleteRetentionPolicy Days"); // Static Website finalProperties.setStaticWebsite(properties.getStaticWebsite()); } context = context == null ? Context.NONE : context; return this.azureBlobStorage.getServices().setPropertiesWithResponseAsync(finalProperties, null, null, context) .map(response -> new SimpleResponse<>(response, null)); } /** * Sets any null fields to "" since the service requires all Cors rules to be set if some are set. * @param originalRule {@link BlobCorsRule} * @return The validated {@link BlobCorsRule} */ private BlobCorsRule validatedCorsRule(BlobCorsRule originalRule) { if (originalRule == null) { return null; } BlobCorsRule validRule = new BlobCorsRule(); validRule.setAllowedHeaders(StorageImplUtils.emptyIfNull(originalRule.getAllowedHeaders())); validRule.setAllowedMethods(StorageImplUtils.emptyIfNull(originalRule.getAllowedMethods())); validRule.setAllowedOrigins(StorageImplUtils.emptyIfNull(originalRule.getAllowedOrigins())); validRule.setExposedHeaders(StorageImplUtils.emptyIfNull(originalRule.getExposedHeaders())); validRule.setMaxAgeInSeconds(originalRule.getMaxAgeInSeconds()); return validRule; } /** * Validates a {@link BlobRetentionPolicy} according to service specs for set properties. * @param retentionPolicy {@link BlobRetentionPolicy} * @param policyName The name of the variable for errors. */ private void validateRetentionPolicy(BlobRetentionPolicy retentionPolicy, String policyName) { if (retentionPolicy == null) { return; } if (retentionPolicy.isEnabled()) { StorageImplUtils.assertInBounds(policyName, retentionPolicy.getDays(), 1, 365); } } /** * Gets a user delegation key for use with this account's blob storage. Note: This method call is only valid when * using {@link TokenCredential} in this object's {@link HttpPipeline}. * *

Code Samples

* * *
     * client.getUserDelegationKey(delegationKeyStartTime, delegationKeyExpiryTime).subscribe(response ->
     *     System.out.printf("User delegation key: %s%n", response.getValue()));
     * 
* * * @param start Start time for the key's validity. Null indicates immediate start. * @param expiry Expiration of the key's validity. * @return A {@link Mono} containing the user delegation key. * @throws IllegalArgumentException If {@code start} isn't null and is after {@code expiry}. * @throws NullPointerException If {@code expiry} is null. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono getUserDelegationKey(OffsetDateTime start, OffsetDateTime expiry) { return getUserDelegationKeyWithResponse(start, expiry).flatMap(FluxUtil::toMono); } /** * Gets a user delegation key for use with this account's blob storage. Note: This method call is only valid when * using {@link TokenCredential} in this object's {@link HttpPipeline}. * *

Code Samples

* * *
     * client.getUserDelegationKeyWithResponse(delegationKeyStartTime, delegationKeyExpiryTime).subscribe(response ->
     *     System.out.printf("User delegation key: %s%n", response.getValue().getValue()));
     * 
* * * @param start Start time for the key's validity. Null indicates immediate start. * @param expiry Expiration of the key's validity. * @return A {@link Mono} containing a {@link Response} whose {@link Response#getValue() value} containing the user * delegation key. * @throws IllegalArgumentException If {@code start} isn't null and is after {@code expiry}. * @throws NullPointerException If {@code expiry} is null. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono> getUserDelegationKeyWithResponse(OffsetDateTime start, OffsetDateTime expiry) { try { return withContext(context -> getUserDelegationKeyWithResponse(start, expiry, context)); } catch (RuntimeException ex) { return monoError(LOGGER, ex); } } Mono> getUserDelegationKeyWithResponse(OffsetDateTime start, OffsetDateTime expiry, Context context) { StorageImplUtils.assertNotNull("expiry", expiry); if (start != null && !start.isBefore(expiry)) { throw LOGGER.logExceptionAsError( new IllegalArgumentException("`start` must be null or a datetime before `expiry`.")); } throwOnAnonymousAccess(); context = context == null ? Context.NONE : context; return this.azureBlobStorage.getServices().getUserDelegationKeyWithResponseAsync( new KeyInfo() .setStart(start == null ? "" : Constants.ISO_8601_UTC_DATE_FORMATTER.format(start)) .setExpiry(Constants.ISO_8601_UTC_DATE_FORMATTER.format(expiry)), null, null, context) .map(rb -> new SimpleResponse<>(rb, rb.getValue())); } /** * Retrieves statistics related to replication for the Blob service. It is only available on the secondary location * endpoint when read-access geo-redundant replication is enabled for the storage account. For more information, see * the * Azure Docs. * *

Code Samples

* * *
     * client.getStatistics().subscribe(response ->
     *     System.out.printf("Geo-replication status: %s%n", response.getGeoReplication().getStatus()));
     * 
* * * @return A {@link Mono} containing the storage account statistics. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono getStatistics() { return getStatisticsWithResponse().flatMap(FluxUtil::toMono); } /** * Retrieves statistics related to replication for the Blob service. It is only available on the secondary location * endpoint when read-access geo-redundant replication is enabled for the storage account. For more information, see * the * Azure Docs. * *

Code Samples

* * *
     * client.getStatisticsWithResponse().subscribe(response ->
     *     System.out.printf("Geo-replication status: %s%n", response.getValue().getGeoReplication().getStatus()));
     * 
* * * @return A {@link Mono} containing a {@link Response} whose {@link Response#getValue() value} containing the * storage account statistics. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono> getStatisticsWithResponse() { try { return withContext(this::getStatisticsWithResponse); } catch (RuntimeException ex) { return monoError(LOGGER, ex); } } Mono> getStatisticsWithResponse(Context context) { throwOnAnonymousAccess(); context = context == null ? Context.NONE : context; return this.azureBlobStorage.getServices().getStatisticsWithResponseAsync(null, null, context) .map(rb -> new SimpleResponse<>(rb, rb.getValue())); } /** * Returns the sku name and account kind for the account. For more information, please see the * Azure Docs. *

Code Samples

* * *
     * client.getAccountInfo().subscribe(response ->
     *     System.out.printf("Account kind: %s, SKU: %s%n", response.getAccountKind(), response.getSkuName()));
     * 
* * * @return A {@link Mono} containing the storage account info. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono getAccountInfo() { return getAccountInfoWithResponse().flatMap(FluxUtil::toMono); } /** * Returns the sku name and account kind for the account. For more information, please see the * Azure Docs. * *

Code Samples

* * *
     * client.getAccountInfoWithResponse().subscribe(response ->
     *     System.out.printf("Account kind: %s, SKU: %s%n", response.getValue().getAccountKind(),
     *         response.getValue().getSkuName()));
     * 
* * * @return A {@link Mono} containing a {@link Response} whose {@link Response#getValue() value} the storage account * info. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono> getAccountInfoWithResponse() { try { return withContext(this::getAccountInfoWithResponse); } catch (RuntimeException ex) { return monoError(LOGGER, ex); } } Mono> getAccountInfoWithResponse(Context context) { throwOnAnonymousAccess(); return this.azureBlobStorage.getServices().getAccountInfoWithResponseAsync(context) .map(rb -> { ServicesGetAccountInfoHeaders hd = rb.getDeserializedHeaders(); return new SimpleResponse<>(rb, new StorageAccountInfo(hd.getXMsSkuName(), hd.getXMsAccountKind(), hd.isXMsIsHnsEnabled())); }); } /** * Get associated account name. * * @return account name associated with this storage resource. */ public String getAccountName() { return this.accountName; } /** * Generates an account SAS for the Azure Storage account using the specified {@link AccountSasSignatureValues}. *

Note : The client must be authenticated via {@link StorageSharedKeyCredential} *

See {@link AccountSasSignatureValues} for more information on how to construct an account SAS.

* *

The snippet below generates a SAS that lasts for two days and gives the user read and list access to blob * containers and file shares.

* *
     * AccountSasPermission permissions = new AccountSasPermission()
     *     .setListPermission(true)
     *     .setReadPermission(true);
     * AccountSasResourceType resourceTypes = new AccountSasResourceType().setContainer(true);
     * AccountSasService services = new AccountSasService().setBlobAccess(true).setFileAccess(true);
     * OffsetDateTime expiryTime = OffsetDateTime.now().plus(Duration.ofDays(2));
     *
     * AccountSasSignatureValues sasValues =
     *     new AccountSasSignatureValues(expiryTime, permissions, services, resourceTypes);
     *
     * // Client must be authenticated via StorageSharedKeyCredential
     * String sas = client.generateAccountSas(sasValues);
     * 
* * * @param accountSasSignatureValues {@link AccountSasSignatureValues} * * @return A {@code String} representing the SAS query parameters. */ public String generateAccountSas(AccountSasSignatureValues accountSasSignatureValues) { return generateAccountSas(accountSasSignatureValues, Context.NONE); } /** * Generates an account SAS for the Azure Storage account using the specified {@link AccountSasSignatureValues}. *

Note : The client must be authenticated via {@link StorageSharedKeyCredential} *

See {@link AccountSasSignatureValues} for more information on how to construct an account SAS.

* *

The snippet below generates a SAS that lasts for two days and gives the user read and list access to blob * containers and file shares.

* *
     * AccountSasPermission permissions = new AccountSasPermission()
     *     .setListPermission(true)
     *     .setReadPermission(true);
     * AccountSasResourceType resourceTypes = new AccountSasResourceType().setContainer(true);
     * AccountSasService services = new AccountSasService().setBlobAccess(true).setFileAccess(true);
     * OffsetDateTime expiryTime = OffsetDateTime.now().plus(Duration.ofDays(2));
     *
     * AccountSasSignatureValues sasValues =
     *     new AccountSasSignatureValues(expiryTime, permissions, services, resourceTypes);
     *
     * // Client must be authenticated via StorageSharedKeyCredential
     * String sas = client.generateAccountSas(sasValues, new Context("key", "value"));
     * 
* * * @param accountSasSignatureValues {@link AccountSasSignatureValues} * @param context Additional context that is passed through the code when generating a SAS. * * @return A {@code String} representing the SAS query parameters. */ public String generateAccountSas(AccountSasSignatureValues accountSasSignatureValues, Context context) { throwOnAnonymousAccess(); return new AccountSasImplUtil(accountSasSignatureValues, this.encryptionScope == null ? null : this.encryptionScope.getEncryptionScope()) .generateSas(SasImplUtils.extractSharedKeyCredential(getHttpPipeline()), context); } /** * Checks if service client was built with credentials. */ private void throwOnAnonymousAccess() { if (anonymousAccess) { throw LOGGER.logExceptionAsError(new IllegalStateException("Service client cannot be accessed without " + "credentials")); } } /** * Restores a previously deleted container. * If the container associated with provided deletedContainerName * already exists, this call will result in a 409 (conflict). * This API is only functional if Container Soft Delete is enabled * for the storage account associated with the container. * *

Code Samples

* * *
     * ListBlobContainersOptions listBlobContainersOptions = new ListBlobContainersOptions();
     * listBlobContainersOptions.getDetails().setRetrieveDeleted(true);
     * client.listBlobContainers(listBlobContainersOptions).flatMap(
     *     deletedContainer -> {
     *         Mono<BlobContainerAsyncClient> blobContainerClient = client.undeleteBlobContainer(
     *             deletedContainer.getName(), deletedContainer.getVersion());
     *         return blobContainerClient;
     *     }
     * ).then().block();
     * 
* * * @param deletedContainerName The name of the previously deleted container. * @param deletedContainerVersion The version of the previously deleted container. * @return A {@link Mono} containing a {@link BlobContainerAsyncClient} used * to interact with the restored container. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono undeleteBlobContainer(String deletedContainerName, String deletedContainerVersion) { try { return this.undeleteBlobContainerWithResponse(new UndeleteBlobContainerOptions(deletedContainerName, deletedContainerVersion)) .flatMap(FluxUtil::toMono); } catch (RuntimeException ex) { return monoError(LOGGER, ex); } } /** * Restores a previously deleted container. The restored container * will be renamed to the destinationContainerName if provided in options. * Otherwise deletedContainerName is used as destination container name. * If the container associated with provided destinationContainerName * already exists, this call will result in a 409 (conflict). * This API is only functional if Container Soft Delete is enabled * for the storage account associated with the container. * *

Code Samples

* * *
     * ListBlobContainersOptions listBlobContainersOptions = new ListBlobContainersOptions();
     * listBlobContainersOptions.getDetails().setRetrieveDeleted(true);
     * client.listBlobContainers(listBlobContainersOptions).flatMap(
     *     deletedContainer -> {
     *         Mono<BlobContainerAsyncClient> blobContainerClient = client.undeleteBlobContainerWithResponse(
     *             new UndeleteBlobContainerOptions(deletedContainer.getName(), deletedContainer.getVersion()))
     *             .map(Response::getValue);
     *         return blobContainerClient;
     *     }
     * ).then().block();
     * 
* * * @param options {@link UndeleteBlobContainerOptions}. * @return A {@link Mono} containing a {@link Response} whose {@link Response#getValue() value} contains a {@link * BlobContainerAsyncClient} used to interact with the restored container. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono> undeleteBlobContainerWithResponse( UndeleteBlobContainerOptions options) { try { return withContext(context -> undeleteBlobContainerWithResponse(options, context)); } catch (RuntimeException ex) { return monoError(LOGGER, ex); } } Mono> undeleteBlobContainerWithResponse( UndeleteBlobContainerOptions options, Context context) { StorageImplUtils.assertNotNull("options", options); boolean hasOptionalDestinationContainerName = options.getDestinationContainerName() != null; String finalDestinationContainerName = hasOptionalDestinationContainerName ? options.getDestinationContainerName() : options.getDeletedContainerName(); context = context == null ? Context.NONE : context; return this.azureBlobStorage.getContainers().restoreWithResponseAsync(finalDestinationContainerName, null, null, options.getDeletedContainerName(), options.getDeletedContainerVersion(), context) .map(response -> new SimpleResponse<>(response, getBlobContainerAsyncClient(finalDestinationContainerName))); } // /** // * Renames an existing blob container. // * // *

Code Samples

// * // * // * // * // * @param sourceContainerName The current name of the container. // * @param destinationContainerName The new name of the container. // * @return A {@link Mono} containing a {@link BlobContainerAsyncClient} used to interact with the renamed container. // */ // @ServiceMethod(returns = ReturnType.SINGLE) // Mono renameBlobContainer(String sourceContainerName, // String destinationContainerName) { // return renameBlobContainerWithResponse(sourceContainerName, // new BlobContainerRenameOptions(destinationContainerName)).flatMap(FluxUtil::toMono); // } // // /** // * Renames an existing blob container. // * // *

Code Samples

// * // * // * // * // * @param sourceContainerName The current name of the container. // * @param options {@link BlobContainerRenameOptions} // * @return A {@link Mono} containing a {@link Response} whose {@link Response#getValue() value} contains a // * {@link BlobContainerAsyncClient} used to interact with the renamed container. // */ // @ServiceMethod(returns = ReturnType.SINGLE) // Mono> renameBlobContainerWithResponse(String sourceContainerName, // BlobContainerRenameOptions options) { // try { // return withContext(context -> renameBlobContainerWithResponse(sourceContainerName, options, context)); // } catch (RuntimeException ex) { // return monoError(logger, ex); // } // } // // Mono> renameBlobContainerWithResponse(String sourceContainerName, // BlobContainerRenameOptions options, Context context) { // BlobContainerAsyncClient destinationContainerClient = getBlobContainerAsyncClient( // options.getDestinationContainerName()); // return destinationContainerClient.renameWithResponseHelper(sourceContainerName, options, context); // } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy