diff --git a/eng/code-quality-reports/src/main/resources/spotbugs/spotbugs-exclude.xml b/eng/code-quality-reports/src/main/resources/spotbugs/spotbugs-exclude.xml
index 5f55e13d99146..bf083e11e8bff 100755
--- a/eng/code-quality-reports/src/main/resources/spotbugs/spotbugs-exclude.xml
+++ b/eng/code-quality-reports/src/main/resources/spotbugs/spotbugs-exclude.xml
@@ -368,6 +368,7 @@
+ *
*/
- public String computeHmac256(final String stringToSign) throws InvalidKeyException {
+ public String computeHmac256(final String stringToSign) {
try {
/*
We must get a new instance of the Mac calculator for each signature calculated because the instances are
@@ -111,8 +117,14 @@ public String computeHmac256(final String stringToSign) throws InvalidKeyExcepti
hmacSha256.init(new SecretKeySpec(this.accountKey, "HmacSHA256"));
byte[] utf8Bytes = stringToSign.getBytes(StandardCharsets.UTF_8);
return Base64.getEncoder().encodeToString(hmacSha256.doFinal(utf8Bytes));
- } catch (final NoSuchAlgorithmException e) {
- throw new Error(e);
+ } catch (final NoSuchAlgorithmException e) {
+ String errorMsg = "There is no such algorithm. Error Details: " + e.getMessage();
+ logger.asWarning().log(errorMsg);
+ throw new RuntimeException(errorMsg);
+ } catch (InvalidKeyException e) {
+ String errorMsg = "Please double check the account key. Error details: " + e.getMessage();
+ logger.asWarning().log(errorMsg);
+ throw new RuntimeException(errorMsg);
}
}
@@ -121,20 +133,20 @@ private String buildStringToSign(URL requestURL, String httpMethod, Map
For more samples, please see the sample file
+ */ +public final class StorageException extends HttpResponseException { + private static final String ERROR_CODE = "x-ms-error-code"; + private final String message; + + StorageException(StorageErrorException e, String responseBody) { + super(e.getMessage(), e.response(), e); + this.message = responseBody; + } + + /** + * @return The error code returned by the service. + */ + public StorageErrorCode errorCode() { + return StorageErrorCode.fromString(super.response().headers().value(ERROR_CODE)); + } + + /** + * @return The message returned by the service. + */ + public String message() { + return this.message; + } + + /** + * @return The status code on the response. + */ + public int statusCode() { + return super.response().statusCode(); + } +} diff --git a/storage/client/file/src/main/java/com/azure/storage/common/policy/RequestRetryOptions.java b/storage/client/file/src/main/java/com/azure/storage/common/policy/RequestRetryOptions.java index edeaf6484ea6a..86e7d0ef35f37 100644 --- a/storage/client/file/src/main/java/com/azure/storage/common/policy/RequestRetryOptions.java +++ b/storage/client/file/src/main/java/com/azure/storage/common/policy/RequestRetryOptions.java @@ -64,6 +64,11 @@ public RequestRetryOptions() { *Sample Code
* *For more samples, please see the samples file
+ * @throws IllegalArgumentException If one of the following case exists: + *Instantiating an Asynchronous Directory Client
+ * + * {@codesnippet com.azure.storage.file.directoryAsyncClient.instantiation} + * + *View {@link DirectoryClientBuilder this} for additional ways to construct the client.
+ * + * @see DirectoryClientBuilder + * @see DirectoryClient + * @see SharedKeyCredential + * @see SASTokenCredential + */ public class DirectoryAsyncClient { + private final AzureFileStorageImpl azureFileStorageClient; + private final String shareName; + private final String directoryPath; + private final String snapshot; + + /** + * Creates a DirectoryAsyncClient that sends requests to the storage directory at {@link AzureFileStorageImpl#url() endpoint}. + * Each service call goes through the {@link HttpPipeline pipeline} in the {@code client}. + * @param azureFileStorageClient Client that interacts with the service interfaces + * @param shareName Name of the share + * @param directoryPath Name of the directory + * @param snapshot The snapshot of the share + */ + DirectoryAsyncClient(AzureFileStorageImpl azureFileStorageClient, String shareName, String directoryPath, String snapshot) { + this.shareName = shareName; + this.directoryPath = directoryPath; + this.snapshot = snapshot; + this.azureFileStorageClient = azureFileStorageClient; + } - DirectoryAsyncClient() { - throw new UnsupportedOperationException(); + /** + * Creates a DirectoryAsyncClient that sends requests to this directory at {@code endpoint}. + * Each service call goes through the {@code httpPipeline}. + * @param endpoint URL for the Storage File service + * @param httpPipeline HttpPipeline that HTTP requests and response flow through + * @param shareName Name of the share + * @param directoryPath Name of the directory + * @param snapshot Optional snapshot of the share + */ + DirectoryAsyncClient(URL endpoint, HttpPipeline httpPipeline, String shareName, String directoryPath, String snapshot) { + this.shareName = shareName; + this.directoryPath = directoryPath; + this.snapshot = snapshot; + this.azureFileStorageClient = new AzureFileStorageBuilder().pipeline(httpPipeline) + .url(endpoint.toString()) + .build(); } - public static DirectoryClientBuilder asyncBuilder() { - throw new UnsupportedOperationException(); + /** + * Get the url of the storage directory client. + * @return the URL of the storage directory client + * @throws RuntimeException If the directory is using a malformed URL. + */ + public URL getDirectoryUrl() { + try { + return new URL(azureFileStorageClient.url()); + } catch (MalformedURLException e) { + throw new RuntimeException(String.format("Invalid URL on %s: %s" + getClass().getSimpleName(), + azureFileStorageClient.url()), e); + } } - public FileAsyncClient getFileClient(String name) { - throw new UnsupportedOperationException(); + /** + * Constructs a FileAsyncClient that interacts with the specified file. + * + *If the file doesn't exist in this directory {@link FileAsyncClient#create(long)} create} in the client will + * need to be called before interaction with the file can happen.
+ * + * @param fileName Name of the file + * @return a FileAsyncClient that interacts with the specified share + */ + public FileAsyncClient getFileClient(String fileName) { + String filePath = directoryPath + "/" + fileName; + return new FileAsyncClient(azureFileStorageClient, shareName, filePath, null); } - public DirectoryAsyncClient getDirectoryClient(String directoryName) { - throw new UnsupportedOperationException(); + /** + * Constructs a DirectoryAsyncClient that interacts with the specified directory. + * + *If the file doesn't exist in this directory {@link DirectoryAsyncClient#create()} create} in the client will + * need to be called before interaction with the directory can happen.
+ * + * @param subDirectoryName Name of the directory + * @return a DirectoryAsyncClient that interacts with the specified directory + */ + public DirectoryAsyncClient getSubDirectoryClient(String subDirectoryName) { + String directoryPath = this.directoryPath + "/" + subDirectoryName; + return new DirectoryAsyncClient(azureFileStorageClient, shareName, directoryPath, snapshot); } + /** + * Creates this directory in the file share and returns a response of {@link DirectoryInfo} to interact with it. + * + *Code Samples
+ * + *Create the directory
+ * + * {@codesnippet com.azure.storage.file.directoryAsyncClient.create} + * + * @return A response containing the directory info and the status of creating the directory. + * @throws StorageErrorException If the directory has already existed, the parent directory does not exist or directory name is an invalid resource name. + */ + public MonoCode Samples
+ * + *Create the directory
+ * + * {@codesnippet com.azure.storage.file.directoryAsyncClient.create#map} + * + * @param metadata Optional metadata to associate with the directory + * @return A response containing the directory info and the status of creating the directory. + * @throws StorageErrorException If the directory has already existed, the parent directory does not exist or directory name is an invalid resource name. + */ public MonoCode Samples
+ * + *Delete the directory
+ * + * {@codesnippet com.azure.storage.file.directoryClient.delete} + * + * @return A response that only contains headers and response status code + * @throws StorageErrorException If the share doesn't exist + */ public MonoCode Samples
+ * + *Retrieve directory properties
+ * + * {@codesnippet com.azure.storage.file.directoryAsyncClient.getProperties} + * + * @return Storage directory properties + */ + public MonoIf {@code null} is passed for the metadata it will clear the metadata associated to the directory.
+ * + *Code Samples
+ * + *Set the metadata to "directory:updatedMetadata"
+ * + * {@codesnippet com.azure.storage.file.directoryAsyncClient.setMetadata#map} + * + *Clear the metadata of the directory
+ * + * {@codesnippet com.azure.storage.file.directoryAsyncClient.setMetadata#map.clearMetadata} + * + * @param metadata Optional metadata to set on the directory, if null is passed the metadata for the directory is cleared + * @return information about the directory + * @throws StorageErrorException If the directory doesn't exist or the metadata contains invalid keys + */ + public MonoCode Samples
+ * + *List all sub-directories and files in the account
+ * + * {@codesnippet com.azure.storage.file.directoryClient.listFilesAndDirectories} + * + * @return {@link FileRef File info} in the storage directory + */ + public FluxCode Samples
+ * + *List all sub-directories with "subdir" prefix and return 10 results in the account
+ * + * {@codesnippet com.azure.storage.file.directoryAsyncClient.listFilesAndDirectories#string-integer} + * + * @param prefix Optional prefix which filters the results to return only files and directories whose name begins with. + * @param maxResults Optional maximum number of files and/or directories to return per page. + * If the request does not specify maxresults or specifies a value greater than 5,000, the server will return up to 5,000 items. + * @return {@link FileRef File info} in this directory with prefix and max number of return results. + */ + public FluxCode Samples
+ * + *Get 10 handles with recursive call.
+ * + * {@codesnippet com.azure.storage.file.directoryAsyncClient.getHandles} + * + * @param maxResult Optional maximum number of results will return per page + * @param recursive Specifies operation should apply to the directory specified in the URI, its files, its subdirectories and their files. + * @return {@link HandleItem handles} in the directory that satisfy the requirements + */ + public FluxCode Samples
+ * + *Force close handles with handles returned by get handles in recursive.
+ * + * {@codesnippet com.azure.storage.file.directoryAsyncClient.forceCloseHandles} + * + * @param handleId Specifies the handle ID to be closed. Use an asterisk ('*') as a wildcard string to specify all handles. + * @param recursive A boolean value that specifies if the operation should also apply to the files and subdirectories of the directory specified in the URI. + * @return The counts of number of handles closed + */ public FluxCode Samples
+ * + *Create the sub directory "subdir"
+ * + * {@codesnippet com.azure.storage.file.directoryAsyncClient.createSubDirectory#string} + * + * @param subDirectoryName Name of the subdirectory + * @return A response containing the subdirectory client and the status of creating the directory. + * @throws StorageErrorException If the subdirectory has already existed, the parent directory does not exist or directory is an invalid resource name. + */ + public MonoCode Samples
+ * + *Create the subdirectory named "subdir", with metadata
+ * + * {@codesnippet com.azure.storage.file.directoryClient.createSubDirectory#string-map} + * + * @param subDirectoryName Name of the subdirectory + * @param metadata Optional metadata to associate with the subdirectory + * @return A response containing the subdirectory client and the status of creating the directory. + * @throws StorageErrorException If the directory has already existed, the parent directory does not exist or subdirectory is an invalid resource name. + */ + public MonoCode Samples
+ * + *Delete the subdirectory named "subdir"
+ * + * {@codesnippet com.azure.storage.file.directoryAsyncClient.deleteSubDirectory#string} + * + * @param subDirectoryName Name of the subdirectory + * @return A response that only contains headers and response status code + * @throws StorageErrorException If the subdirectory doesn't exist, the parent directory does not exist or subdirectory name is an invalid resource name. + */ + public MonoCode Samples
+ * + *Create 1k file with named "myFile"
+ * + * {@codesnippet com.azure.storage.file.directoryAsyncClient.createFile#string-long} + * + * @param fileName Name of the file + * @param maxSize Size of the file + * @return A response containing the FileAsyncClient and the status of creating the directory. + * @throws StorageErrorException If the file has already existed, the parent directory does not exist or file name is an invalid resource name. + */ + public MonoCode Samples
+ * + *Create the file named "myFile"
+ * + * {@codesnippet com.azure.storage.file.directoryAsyncClient.createFile#string-long-fileHTTPHeaders-map} + * + * @param fileName Name of the file + * @param maxSize Max size of the file + * @param httpHeaders the Http headers set to the file + * @param metadata Optional name-value pairs associated with the file as metadata. Metadata names must adhere to the naming rules. + * @return A response containing the directory info and the status of creating the directory. + * @throws StorageErrorException If the directory has already existed, the parent directory does not exist or file name is an invalid resource name. + */ + public MonoCode Samples
+ * + *Delete the file "filetest"
+ * + * {@codesnippet com.azure.storage.file.directoryAsyncClient.deleteFile#string} + * + * @param fileName Name of the file + * @return A response that only contains headers and response status code + * @throws StorageErrorException If the directory doesn't exist or the file doesn't exist or file name is an invalid resource name. + */ public MonoCode Samples
+ * + *Get the share snapshot id.
+ * + * {@codesnippet com.azure.storage.file.directoryAsyncClient.getShareSnapshotId} + * + * @return The snapshot id which is a unique {@code DateTime} value that identifies the share snapshot to its base share. + */ + public String getShareSnapshotId() { + return this.snapshot; + } + + private ResponseInstantiating an Synchronous Directory Client
+ * + * {@codesnippet com.azure.storage.file.directoryClient.instantiation} + * + *View {@link DirectoryClientBuilder this} for additional ways to construct the client.
+ * + * @see DirectoryClientBuilder + * @see DirectoryClient + * @see SharedKeyCredential + * @see SASTokenCredential + */ public class DirectoryClient { - private final DirectoryAsyncClient client; + private final DirectoryAsyncClient directoryAsyncClient; + + /** + * Creates a DirectoryClient that wraps a DirectoryAsyncClient and blocks requests. + * + * @param directoryAsyncClient DirectoryAsyncClient that is used to send requests + */ + DirectoryClient(DirectoryAsyncClient directoryAsyncClient) { + this.directoryAsyncClient = directoryAsyncClient; + } + + /** + * Get the url of the storage directory client. + * @return the URL of the storage directory client. + * @throws RuntimeException If the directory is using a malformed URL. + */ + public URL getDirectoryUrl() { + return directoryAsyncClient.getDirectoryUrl(); + } + + /** + * Constructs a FileClient that interacts with the specified file. + * + *If the file doesn't exist in this directory {@link FileClient#create(long)} create} in the client will + * need to be called before interaction with the file can happen.
+ * + * @param fileName Name of the file + * @return a FileClient that interacts with the specified share + */ + public FileClient getFileClient(String fileName) { + return new FileClient(directoryAsyncClient.getFileClient(fileName)); + } + + /** + * Constructs a DirectoryClient that interacts with the specified directory. + * + *If the file doesn't exist in this directory {@link DirectoryClient#create()} create} in the client will + * need to be called before interaction with the directory can happen.
+ * + * @param subDirectoryName Name of the directory + * @return a DirectoryClient that interacts with the specified directory + */ + public DirectoryClient getSubDirectoryClient(String subDirectoryName) { + return new DirectoryClient(directoryAsyncClient.getSubDirectoryClient(subDirectoryName)); + } + + /** + * Creates a directory in the file share and returns a response of {@link DirectoryInfo} to interact with it. + * + *Code Samples
+ * + *Create the directory
+ * + * {@codesnippet com.azure.storage.file.directoryClient.createDirectory} + * + * @return A response containing the directory info and the status of creating the directory. + * @throws StorageErrorException If the directory has already existed, the parent directory does not exist or directory name is an invalid resource name. + */ + public ResponseCode Samples
+ * + *Create the directory
+ * + * {@codesnippet com.azure.storage.file.directoryClient.create#map} + * + * @param metadata Optional metadata to associate with the directory. + * @return A response containing the directory info and the status of creating the directory. + * @throws StorageErrorException If the directory has already existed, the parent directory does not exist or directory name is an invalid resource name. + */ + public ResponseCode Samples
+ * + *Delete the directory
+ * + * {@codesnippet com.azure.storage.file.directoryClient.delete} + * + * @return A response that only contains headers and response status code + * @throws StorageErrorException If the share doesn't exist + */ + public VoidResponse delete() { + return directoryAsyncClient.delete().block(); } - public FileClient getFileClient(String name) { - throw new UnsupportedOperationException(); + /** + * Retrieves the properties of this directory. + * The properties includes directory metadata, last modified date, is server encrypted, and eTag. + * + *Code Samples
+ * + *Retrieve directory properties
+ * + * {@codesnippet com.azure.storage.file.directoryClient.getProperties} + * + * @return Storage directory properties + */ + public ResponseIf {@code null} is passed for the metadata it will clear the metadata associated to the directory.
+ * + *Code Samples
+ * + *Set the metadata to "directory:updatedMetadata"
+ * + * {@codesnippet com.azure.storage.file.directoryClient.setMetadata#map} + * + *Clear the metadata of the directory
+ * + * {@codesnippet com.azure.storage.file.directoryClient.setMetadata#map.clearMetadata} + * + * @param metadata Optional metadata to set on the directory, if null is passed the metadata for the directory is cleared + * @return information about the directory + * @throws StorageErrorException If the directory doesn't exist or the metadata contains invalid keys + */ + public ResponseCode Samples
+ * + *List all sub-directories and files in the account
+ * + * {@codesnippet com.azure.storage.file.directoryClient.listFilesAndDirectories} + * + * @return {@link FileRef File info} in the storage directory + */ + public IterableCode Samples
+ * + *List all sub-directories and files in this directory with "subdir" prefix and return 10 results in the account
+ * + * {@codesnippet com.azure.storage.file.directoryClient.listFilesAndDirectories#string-integer} + * + * @param prefix Optional prefix which filters the results to return only files and directories whose name begins with. + * @param maxResults Optional maximum number of files and/or directories to return per page. + * If the request does not specify maxresults or specifies a value greater than 5,000, the server will return up to 5,000 items. + * @return {@link FileRef File info} in this directory with prefix and max number of return results. + */ + public IterableCode Samples
+ * + *Get 10 handles with recursive call.
+ * + * {@codesnippet com.azure.storage.file.directoryClient.getHandles} + * + * @param maxResult Optional maximum number of results will return per page + * @param recursive Specifies operation should apply to the directory specified in the URI, its files, its subdirectories and their files. + * @return {@link HandleItem handles} in the directory that satisfy the requirements + */ + public IterableCode Samples
+ * + *Force close handles with handles returned by get handles in recursive.
+ * + * {@codesnippet com.azure.storage.file.directoryClient.forceCloseHandles} + * + * @param handleId Specifies the handle ID to be closed. Use an asterisk ('*') as a wildcard string to specify all handles. + * @param recursive A boolean value that specifies if the operation should also apply to the files and subdirectories of the directory specified in the URI. + * @return The counts of number of handles closed. + */ + public IterableCode Samples
+ * + *Create the sub directory "subdir"
+ * + * {@codesnippet com.azure.storage.file.directoryClient.createSubDirectory#string} + * + * @param subDirectoryName Name of the subdirectory + * @return A response containing the subdirectory client and the status of creating the directory. + * @throws StorageErrorException If the subdirectory has already existed, the parent directory does not exist or directory is an invalid resource name. + */ + public ResponseCode Samples
+ * + *Create the subdirectory named "subdir", with metadata
+ * + * {@codesnippet com.azure.storage.file.directoryClient.createSubDirectory#string-map} + * + * @param subDirectoryName Name of the subdirectory + * @param metadata Optional metadata to associate with the subdirectory + * @return A response containing the subdirectory client and the status of creating the directory. + * @throws StorageErrorException If the directory has already existed, the parent directory does not exist or subdirectory is an invalid resource name. + */ + public ResponseCode Samples
+ * + *Delete the subdirectory named "subdir"
+ * + * {@codesnippet com.azure.storage.file.directoryClient.deleteSubDirectory#string} + * + * @param subDirectoryName Name of the subdirectory + * @return A response that only contains headers and response status code + * @throws StorageErrorException If the subdirectory doesn't exist, the parent directory does not exist or subdirectory name is an invalid resource name. + */ + public VoidResponse deleteSubDirectory(String subDirectoryName) { + return directoryAsyncClient.deleteSubDirectory(subDirectoryName).block(); } - public MonoCode Samples
+ * + *Create 1k file with named "myFile"
+ * + * {@codesnippet com.azure.storage.file.directoryClient.createFile#string-long} + * + * @param fileName Name of the file + * @param maxSize Size of the file + * @return A response containing the FileClient and the status of creating the directory. + * @throws StorageErrorException If the file has already existed, the parent directory does not exist or file name is an invalid resource name. + */ + public ResponseCode Samples
+ * + *Create the file named "myFile"
+ * + * {@codesnippet com.azure.storage.file.directoryClient.createFile#string-long-fileHTTPHeaders-map} + * + * @param fileName Name of the file + * @param maxSize Max size of the file + * @param httpHeaders the Http headers set to the file + * @param metadata Optional name-value pairs associated with the file as metadata. Metadata names must adhere to the naming rules. + * @return A response containing the directory info and the status of creating the directory. + * @throws StorageErrorException If the directory has already existed, the parent directory does not exist or file name is an invalid resource name. + */ + public ResponseCode Samples
+ * + *Delete the file "filetest"
+ * + * {@codesnippet com.azure.storage.file.directoryClient.deleteFile#string} + * + * @param fileName Name of the file + * @return A response that only contains headers and response status code + * @throws StorageErrorException If the directory doesn't exist or the file doesn't exist or file name is an invalid resource name. + */ + public VoidResponse deleteFile(String fileName) { + return directoryAsyncClient.deleteFile(fileName).block(); } - public MonoCode Samples
+ * + *Get the share snapshot id.
+ * + * {@codesnippet com.azure.storage.file.directoryClient.getShareSnapshotId} + * + * @return The snapshot id which is a unique {@code DateTime} value that identifies the share snapshot to its base share. + */ + public String getShareSnapshotId() { + return directoryAsyncClient.getShareSnapshotId(); } } diff --git a/storage/client/file/src/main/java/com/azure/storage/file/DirectoryClientBuilder.java b/storage/client/file/src/main/java/com/azure/storage/file/DirectoryClientBuilder.java index 7bbd3cb138d2e..e5b7129cc046e 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/DirectoryClientBuilder.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/DirectoryClientBuilder.java @@ -3,7 +3,357 @@ package com.azure.storage.file; +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.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.RetryPolicy; +import com.azure.core.http.policy.UserAgentPolicy; +import com.azure.core.implementation.http.policy.spi.HttpPolicyProviders; +import com.azure.core.util.configuration.Configuration; +import com.azure.core.util.configuration.ConfigurationManager; +import com.azure.storage.common.credentials.SASTokenCredential; +import com.azure.storage.common.credentials.SharedKeyCredential; +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; + +/** + * This class provides a fluent builder API to help aid the configuration and instantiation of the {@link DirectoryClient FileClients} + * and {@link DirectoryAsyncClient FileAsyncClients}, calling {@link DirectoryClientBuilder#buildClient() buildClient} + * constructs an instance of FileClient and calling {@link DirectoryClientBuilder#buildAsyncClient() buildAsyncClient} + * constructs an instance of FileAsyncClient. + * + *The client needs the endpoint of the Azure Storage File service, name of the share, and authorization credential. + * {@link DirectoryClientBuilder#endpoint(String) endpoint} gives the builder the endpoint and may give the builder the + * {@link DirectoryClientBuilder#shareName(String)}, {@link DirectoryClientBuilder#directoryPath(String)} and a {@link SASTokenCredential} that authorizes the client.
+ * + *Instantiating a synchronous Directory Client with SAS token
+ * {@codesnippet com.azure.storage.file.directoryClient.instantiation.sastoken} + * + *Instantiating an Asynchronous Directory Client with SAS token
+ * {@codesnippet com.azure.storage.file.directoryClient.instantiation.sastoken} + * + *If the {@code endpoint} doesn't contain the query parameters to construct a {@code SASTokenCredential} they may + * be set using {@link DirectoryClientBuilder#credential(SASTokenCredential) credential}.
+ * + * {@codesnippet com.azure.storage.file.directoryClient.instantiation.credential} + * + * {@codesnippet com.azure.storage.file.directoryAsyncClient.instantiation.credential} + * + *Another way to authenticate the client is using a {@link SharedKeyCredential}. To create a SharedKeyCredential + * a connection string from the Storage File service must be used. Set the SharedKeyCredential with + * {@link DirectoryClientBuilder#connectionString(String) connectionString}. If the builder has both a SASTokenCredential and + * SharedKeyCredential the SharedKeyCredential will be preferred when authorizing requests sent to the service.
+ * + *Instantiating a synchronous Directory Client with connection string.
+ * {@codesnippet com.azure.storage.file.directoryClient.instantiation.connectionstring} + * + *Instantiating an Asynchronous Directory Client with connection string.
+ * {@codesnippet com.azure.storage.file.directoryAsyncClient.instantiation.connectionstring} + * + * @see DirectoryClient + * @see DirectoryAsyncClient + * @see SASTokenCredential + * @see SharedKeyCredential + */ public class DirectoryClientBuilder { + private static final String ACCOUNT_NAME = "accountname"; + private final List+ * If {@link DirectoryClientBuilder#pipeline(HttpPipeline) pipeline} is set, then the {@code pipeline} and + * {@link DirectoryClientBuilder#endpoint(String) endpoint} are used to create the + * {@link DirectoryAsyncClient client}. All other builder settings are ignored. + *
+ * + * @return A ShareAsyncClient with the options set from the builder. + * @throws NullPointerException If {@code shareName} is {@code null} or {@code shareName} is {@code null}. + * @throws IllegalArgumentException If neither a {@link SharedKeyCredential} or {@link SASTokenCredential} has been set. + */ + public DirectoryAsyncClient buildAsyncClient() { + Objects.requireNonNull(shareName); + Objects.requireNonNull(directoryPath); + + if (pipeline != null) { + return new DirectoryAsyncClient(endpoint, pipeline, shareName, directoryPath, snapshot); + } + + if (sasTokenCredential == null && sharedKeyCredential == null) { + throw new IllegalArgumentException("Credentials are required for authorization"); + } + + // Closest to API goes first, closest to wire goes last. + final List+ * If {@link DirectoryClientBuilder#pipeline(HttpPipeline) pipeline} is set, then the {@code pipeline} and + * {@link DirectoryClientBuilder#endpoint(String) endpoint} are used to create the + * {@link DirectoryClient client}. All other builder settings are ignored. + *
+ * + * @return A DirectoryClient with the options set from the builder. + * @throws NullPointerException If {@code endpoint}, {@code shareName} or {@code directoryPath} is {@code null}. + * @throws IllegalArgumentException If neither a {@link SharedKeyCredential} or {@link SASTokenCredential} has been set. + */ + public DirectoryClient buildClient() { + return new DirectoryClient(this.buildAsyncClient()); + } + + /** + * Sets the endpoint for the Azure Storage File instance that the client will interact with. + * + *The first path segment, if the endpoint contains path segments, will be assumed to be the name of the share + * that the client will interact with. Rest of the path segments should be the path of the directory.
+ * + *Query parameters of the endpoint will be parsed using {@link SASTokenCredential#fromQuery(String)} in an + * attempt to generate a {@link SASTokenCredential} to authenticate requests sent to the service.
+ * + * @param endpoint The URL of the Azure Storage File instance to send service requests to and receive responses from. + * @return the updated DirectoryClientBuilder object + * @throws IllegalArgumentException If {@code endpoint} is {@code null} or is an invalid URL + */ + public DirectoryClientBuilder endpoint(String endpoint) { + Objects.requireNonNull(endpoint); + try { + URL fullURL = new URL(endpoint); + this.endpoint = new URL(fullURL.getProtocol() + "://" + fullURL.getHost()); + String[] pathSegments = fullURL.getPath().split("/"); + int length = pathSegments.length; + this.shareName = length >= 2 ? pathSegments[1] : this.shareName; + this.directoryPath = length >= 3 ? pathSegments[2] : this.directoryPath; + + // Attempt to get the SAS token from the URL passed + this.sasTokenCredential = SASTokenCredential.fromQuery(fullURL.getQuery()); + if (this.sasTokenCredential != null) { + this.sharedKeyCredential = null; + } + } catch (MalformedURLException ex) { + throw new IllegalArgumentException("The Azure Storage Directory endpoint url is malformed."); + } + + return this; + } + + /** + * Sets the {@link SASTokenCredential} used to authenticate requests sent to the File service. + * + * @param credential SAS token credential generated from the Storage account that authorizes requests + * @return the updated DirectoryClientBuilder object + * @throws NullPointerException If {@code credential} is {@code null}. + */ + public DirectoryClientBuilder credential(SASTokenCredential credential) { + this.sasTokenCredential = Objects.requireNonNull(credential); + this.sharedKeyCredential = null; + return this; + } + + /** + * Sets the {@link SharedKeyCredential} used to authenticate requests sent to the File service. + * + * @param credential Shared key credential generated from the Storage account that authorizes requests + * @return the updated ShareClientBuilder object + * @throws NullPointerException If {@code credential} is {@code null}. + */ + public DirectoryClientBuilder credential(SharedKeyCredential credential) { + this.sharedKeyCredential = Objects.requireNonNull(credential); + this.sasTokenCredential = null; + return this; + } + + /** + * Creates a {@link SharedKeyCredential} from the {@code connectionString} used to authenticate requests sent to the + * File service. + * + * @param connectionString Connection string from the Access Keys section in the Storage account + * @return the updated DirectoryClientBuilder object + * @throws NullPointerException If {@code connectionString} is {@code null}. + */ + public DirectoryClientBuilder connectionString(String connectionString) { + Objects.requireNonNull(connectionString); + this.sharedKeyCredential = SharedKeyCredential.fromConnectionString(connectionString); + getEndPointFromConnectionString(connectionString); + return this; + } + + private void getEndPointFromConnectionString(String connectionString) { + MapIf {@code pipeline} is set, all other settings are ignored, aside from {@link DirectoryClientBuilder#endpoint(String) endpoint}, + * {@link DirectoryClientBuilder#shareName(String) shareName} @{link DirectoryClientBuilder#directoryPath(String) filePath}, and {@link DirectoryClientBuilder#snapshot(String) snaphotShot} + * when building clients.
+ * + * @param pipeline The HTTP pipeline to use for sending service requests and receiving responses. + * @return The updated DirectoryClientBuilder object. + * @throws NullPointerException If {@code pipeline} is {@code null}. + */ + public DirectoryClientBuilder pipeline(HttpPipeline pipeline) { + this.pipeline = Objects.requireNonNull(pipeline); + 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 builder, defaults to Configuration.NONE + * @param configuration configuration store + * @return the updated DirectoryClientBuilder object + */ + public DirectoryClientBuilder configuration(Configuration configuration) { + this.configuration = configuration; + return this; + } -// connectionString, shareName, directoryName, FileClientOptions, SharedKeyCredential, + /** + * Sets the share snapshot that the constructed clients will interact with. This snapshot must be linked to the share + * that has been specified in the builder. + * + * @param snapshot Identifier of the share snapshot + * @return the updated DirectoryClientBuilder object. + */ + public DirectoryClientBuilder snapshot(String snapshot) { + this.snapshot = snapshot; + return this; + } } diff --git a/storage/client/file/src/main/java/com/azure/storage/file/FileAsyncClient.java b/storage/client/file/src/main/java/com/azure/storage/file/FileAsyncClient.java index 0297818f4650b..2dd054d060a2e 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/FileAsyncClient.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/FileAsyncClient.java @@ -3,77 +3,734 @@ package com.azure.storage.file; +import com.azure.core.http.HttpPipeline; import com.azure.core.http.rest.Response; +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.core.util.logging.ClientLogger; +import com.azure.storage.common.credentials.SASTokenCredential; +import com.azure.storage.common.credentials.SharedKeyCredential; +import com.azure.storage.file.implementation.AzureFileStorageBuilder; +import com.azure.storage.file.implementation.AzureFileStorageImpl; +import com.azure.storage.file.models.CopyStatusType; import com.azure.storage.file.models.FileCopyInfo; import com.azure.storage.file.models.FileDownloadInfo; +import com.azure.storage.file.models.FileGetPropertiesHeaders; import com.azure.storage.file.models.FileHTTPHeaders; import com.azure.storage.file.models.FileInfo; +import com.azure.storage.file.models.FileMetadataInfo; import com.azure.storage.file.models.FileProperties; -import com.azure.storage.file.models.FileRangeInfo; +import com.azure.storage.file.models.FileRange; import com.azure.storage.file.models.FileRangeWriteType; import com.azure.storage.file.models.FileUploadInfo; +import com.azure.storage.file.models.FileUploadRangeHeaders; +import com.azure.storage.file.models.FilesCreateResponse; +import com.azure.storage.file.models.FilesDownloadResponse; +import com.azure.storage.file.models.FilesForceCloseHandlesResponse; +import com.azure.storage.file.models.FilesGetPropertiesResponse; +import com.azure.storage.file.models.FilesGetRangeListResponse; +import com.azure.storage.file.models.FilesListHandlesResponse; +import com.azure.storage.file.models.FilesSetHTTPHeadersResponse; +import com.azure.storage.file.models.FilesSetMetadataResponse; +import com.azure.storage.file.models.FilesStartCopyResponse; +import com.azure.storage.file.models.FilesUploadRangeResponse; import com.azure.storage.file.models.HandleItem; +import com.azure.storage.file.models.StorageErrorException; import io.netty.buffer.ByteBuf; +import java.io.File; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.channels.AsynchronousFileChannel; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.time.Duration; +import java.time.OffsetDateTime; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeoutException; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import reactor.core.scheduler.Schedulers; -import java.util.Map; - +/** + * This class provides a client that contains all the operations for interacting with file in Azure Storage File Service. + * Operations allowed by the client are creating, copying, uploading, downloading, deleting and listing on a file, retrieving properties, setting metadata + * and list or force close handles of the file. + * + *Instantiating an Asynchronous File Client
+ * + * {@codesnippet com.azure.storage.file.fileAsyncClient.instantiation} + * + *View {@link FileClientBuilder this} for additional ways to construct the client.
+ * + * @see FileClientBuilder + * @see FileClient + * @see SharedKeyCredential + * @see SASTokenCredential + */ public class FileAsyncClient { - FileAsyncClient() { - throw new UnsupportedOperationException(); + private final ClientLogger logger = new ClientLogger(FileAsyncClient.class); + private static final long FILE_DEFAULT_BLOCK_SIZE = 4 * 1024 * 1024L; + private static final long DOWNLOAD_UPLOAD_CHUNK_TIMEOUT = 300; + + private final AzureFileStorageImpl azureFileStorageClient; + private final String shareName; + private final String filePath; + private final String snapshot; + + /** + * Creates a FileAsyncClient that sends requests to the storage file at {@link AzureFileStorageImpl#url() endpoint}. + * Each service call goes through the {@link HttpPipeline pipeline} in the {@code client}. + * @param azureFileStorageClient Client that interacts with the service interfaces + * @param shareName Name of the share + * @param filePath Path to the file + * @param snapshot The snapshot of the share + */ + FileAsyncClient(AzureFileStorageImpl azureFileStorageClient, String shareName, String filePath, String snapshot) { + this.shareName = shareName; + this.filePath = filePath; + this.snapshot = snapshot; + this.azureFileStorageClient = azureFileStorageClient; + } + + /** + * Creates a FileAsyncClient that sends requests to the storage account at {@code endpoint}. + * Each service call goes through the {@code httpPipeline}. + * @param endpoint URL for the Storage File service + * @param httpPipeline HttpPipeline that HTTP requests and response flow through + * @param shareName Name of the share + * @param filePath Path to the file + * @param snapshot Optional snapshot of the share + */ + FileAsyncClient(URL endpoint, HttpPipeline httpPipeline, String shareName, String filePath, String snapshot) { + this.shareName = shareName; + this.filePath = filePath; + this.snapshot = snapshot; + this.azureFileStorageClient = new AzureFileStorageBuilder().pipeline(httpPipeline) + .url(endpoint.toString()) + .build(); } - public static FileClientBuilder asyncBuilder() { - throw new UnsupportedOperationException(); + /** + * Get the url of the storage file client. + * @return the URL of the storage file client + * @throws RuntimeException If the file is using a malformed URL. + */ + public URL getFileUrl() { + try { + return new URL(azureFileStorageClient.url()); + } catch (MalformedURLException e) { + throw new RuntimeException(String.format("Invalid URL on %s: %s" + getClass().getSimpleName(), + azureFileStorageClient.url()), e); + } } + /** + * Creates a file in the storage account and returns a response of {@link FileInfo} to interact with it. + * + *Code Samples
+ * + *Create the file with size 1KB.
+ * + * {@codesnippet com.azure.storage.file.fileClient.create} + * + * @param maxSize The maximum size in bytes for the file, up to 1 TiB. + * @return A response containing the file info and the status of creating the file. + * @throws StorageErrorException If the file has already existed, the parent directory does not exist or fileName is an invalid resource name. + */ + public MonoCode Samples
+ * + *Create the file with length of 1024 bytes, some headers and metadata.
+ * + * {@codesnippet com.azure.storage.file.fileAsyncClient.create#long-filehttpheaders-map} + * + * @param maxSize The maximum size in bytes for the file, up to 1 TiB. + * @param httpHeaders Additional parameters for the operation. + * @param metadata Optional name-value pairs associated with the file as metadata. Metadata names must adhere to the naming rules. + * @see C# identifiers + * @return A response containing the directory info and the status of creating the directory. + * @throws StorageErrorException If the directory has already existed, the parent directory does not exist or directory is an invalid resource name. + */ public MonoCode Samples
+ * + *Copy file from source url to the {@code filePath}
+ * + * {@codesnippet com.azure.storage.file.fileAsyncClient.startCopy#string-map} + * + * @param sourceUrl Specifies the URL of the source file or blob, up to 2 KB in length. + * @param metadata Optional name-value pairs associated with the file as metadata. Metadata names must adhere to the naming rules. + * * @see C# identifiers + * @return A response containing the file copy info and the status of copying the file. + */ public MonoCode Samples
+ * + *Abort copy file from copy id("someCopyId")
+ * + * {@codesnippet com.azure.storage.file.fileAsyncClient.abortCopy#string} + * + * @param copyId Specifies the copy id which has copying pending status associate with it. + * @return A response containing the status of aborting copy the file. + */ public MonoCode Samples
+ * + *Download the file to current folder.
+ * + * {@codesnippet com.azure.storage.file.fileAsyncClient.downloadToFile#string} + * + * @param downloadFilePath The path where store the downloaded file + * @return An empty response. + */ + public MonoCode Samples
+ * + *Download the file from 1024 to 2048 bytes to current folder.
+ * + * {@codesnippet com.azure.storage.file.fileAsyncClient.downloadToFile#string-filerange} + * + * @param downloadFilePath The path where store the downloaded file + * @param range Optional byte range which returns file data only from the specified range. + * @return An empty response. + */ + public MonoCode Samples
+ * + *Download the file with its metadata and properties.
+ * + * {@codesnippet com.azure.storage.file.fileAsyncClient.downloadWithProperties} + * + * @return A response that only contains headers and response status code + */ + public MonoCode Samples
+ * + *Download the file from 1024 to 2048 bytes with its metadata and properties and without the contentMD5.
+ * + * {@codesnippet com.azure.storage.file.fileAsyncClient.downloadWithProperties#filerange-boolean} + * + * @param range Optional byte range which returns file data only from the specified range. + * @param rangeGetContentMD5 Optional boolean which the service returns the MD5 hash for the range when it sets to true, as long as the range is less than or equal to 4 MB in size. + * @return A response that only contains headers and response status code + */ + public MonoCode Samples
+ * + *Delete the file
+ * + * {@codesnippet com.azure.storage.file.fileAsyncClient.delete} + * + * @return A response that only contains headers and response status code + * @throws StorageErrorException If the directory doesn't exist or the file doesn't exist. + */ public MonoCode Samples
+ * + *Retrieve file properties
+ * + * {@codesnippet com.azure.storage.file.fileAsyncClient.getProperties} + * + * @return Storage file properties + */ + public MonoIf {@code null} is passed for the httpHeaders it will clear the httpHeaders associated to the file.
+ * + *Code Samples
+ * + *Set the httpHeaders of contentType of "text/plain"
+ * + * {@codesnippet com.azure.storage.file.fileAsyncClient.setHttpHeaders#long-filehttpheaders} + * + *Clear the metadata of the file
+ * + * {@codesnippet com.azure.storage.file.fileAsyncClient.setHttpHeaders#long-filehttpheaders.clearHttpHeaders} + * + * @param newFileSize New file size of the file + * @param httpHeaders Resizes a file to the specified size. If the specified byte value is less than the current size of the file, then all ranges above the specified byte value are cleared. + * @return Response of the information about the file + * @throws IllegalArgumentException thrown if parameters fail the validation. + */ public MonoIf {@code null} is passed for the metadata it will clear the metadata associated to the file.
+ * + *Code Samples
+ * + *Set the metadata to "file:updatedMetadata"
+ * + * {@codesnippet com.azure.storage.file.fileAsyncClient.setMetadata#map} + * + *Clear the metadata of the file
+ * + * {@codesnippet com.azure.storage.file.fileAsyncClient.setMetadata#map.clearMetadata} + * + * @param metadata Options.Metadata to set on the file, if null is passed the metadata for the file is cleared + * @return information about the file + * @throws StorageErrorException If the file doesn't exist or the metadata contains invalid keys + */ + public MonoCode Samples
+ * + *Upload "default" to the file.
+ * + * {@codesnippet com.azure.storage.file.fileAsyncClient.upload#flux-long} + * + * @param data The data which will upload to the storage file. + * @param length Specifies the number of bytes being transmitted in the request body. When the FileRangeWriteType is set to clear, the value of this header must be set to zero.. + * @return A response that only contains headers and response status code + * @throws StorageErrorException If you attempt to upload a range that is larger than 4 MB, the service returns status code 413 (Request Entity Too Large) + */ + public MonoCode Samples
+ * + *Upload the file from 1024 to 2048 bytes with its metadata and properties and without the contentMD5.
+ * + * {@codesnippet com.azure.storage.file.fileAsyncClient.upload#bytebuf-long-int-filerangewritetype} + * + * @param data The data which will upload to the storage file. + * @param offset Optional starting point of the upload range. It will start from the beginning if it is {@code null} + * @param length Specifies the number of bytes being transmitted in the request body. When the FileRangeWriteType is set to clear, the value of this header must be set to zero. + * @param type You may specify one of the following options: + *Code Samples
+ * + *Upload the file from the source file path.
+ * + * {@codesnippet com.azure.storage.file.fileAsyncClient.uploadFromFile#string} + * + * @param uploadFilePath The path where store the source file to upload + * @return An empty response. + */ + public MonoCode Samples
+ * + *Upload the file from the source file path.
+ * + * (@codesnippet com.azure.storage.file.fileAsyncClient.uploadFromFile#string-filerangewritetype} + * + * @param uploadFilePath The path where store the source file to upload + * @param type You may specify one of the following options: + *Code Samples
+ * + *List all ranges for the file client.
+ * + * {@codesnippet com.azure.storage.file.fileAsyncClient.listRanges} + * + * @return {@link FileRange ranges} in the files. + */ + public FluxCode Samples
+ * + *List all ranges within the file range from 1KB to 2KB.
+ * + * {@codesnippet com.azure.storage.file.fileAsyncClient.listRanges#filerange} + * + * @param range Optional byte range which returns file data only from the specified range. + * @return {@link FileRange ranges} in the files that satisfy the requirements + */ + public FluxCode Samples
+ * + *List all handles for the file client.
+ * + * {@codesnippet com.azure.storage.file.fileAsyncClient.listHandles} + * + * @return {@link HandleItem handles} in the files that satisfy the requirements + */ + public FluxCode Samples
+ * + *List 10 handles for the file client.
+ * + * {@codesnippet com.azure.storage.file.fileAsyncClient.listHandles#integer} + * + * @param maxResults Optional maximum number of results will return per page + * @return {@link HandleItem handles} in the file that satisfy the requirements + */ + public FluxCode Samples
+ * + *Force close handles with handles returned by list handles in recursive.
+ * + * {@codesnippet com.azure.storage.file.fileAsyncClient.forceCloseHandles#string} + * + * @param handleId Specifies the handle ID to be closed. Use an asterisk ('*') as a wildcard string to specify all handles. + * @return The counts of number of handles closed + */ public FluxCode Samples
+ * + *Get the share snapshot id.
+ * + * {@codesnippet com.azure.storage.file.fileAsyncClient.getShareSnapshotId} + * + * @return The snapshot id which is a unique {@code DateTime} value that identifies the share snapshot to its base share. + */ + public String getShareSnapshotId() { + return this.snapshot; + } + + private FluxInstantiating a synchronous File Client
+ * + * {@codesnippet com.azure.storage.file.fileClient.instantiation} + * + *View {@link FileClientBuilder this} for additional ways to construct the client.
+ * + * @see FileClientBuilder + * @see FileAsyncClient + * @see SharedKeyCredential + * @see SASTokenCredential + */ public class FileClient { - private final FileAsyncClient client; + private final FileAsyncClient fileAsyncClient; + + /** + * Creates a FileClient that wraps a FileAsyncClient and blocks requests. + * + * @param fileAsyncClient FileAsyncClient that is used to send requests + */ + FileClient(FileAsyncClient fileAsyncClient) { + this.fileAsyncClient = fileAsyncClient; + } + + /** + * Get the url of the storage file client. + * @return the URL of the storage file client. + * @throws RuntimeException If the file is using a malformed URL. + */ + public URL getFileUrl() { + return fileAsyncClient.getFileUrl(); + } + + /** + * Creates a file in the storage account and returns a response of {@link FileInfo} to interact with it. + * + *Code Samples
+ * + *Create the file with length of 1024 bytes, some headers and metadata.
+ * + * {@codesnippet com.azure.storage.file.fileClient.create} + * + * @param maxSize The maximum size in bytes for the file, up to 1 TiB. + * @return A response containing the file info and the status of creating the file. + * @throws StorageErrorException If the file has already existed, the parent directory does not exist or fileName is an invalid resource name. + */ + public ResponseCode Samples
+ * + *Create the file with length of 1024 bytes, some headers and metadata.
+ * + * {@codesnippet com.azure.storage.file.fileClient.create#long-filehttpheaders-map} + * + * @param maxSize The maximum size in bytes for the file, up to 1 TiB. + * @param httpHeaders Additional parameters for the operation. + * @param metadata Optional name-value pairs associated with the file as metadata. Metadata names must adhere to the naming rules. + * @see C# identifiers + * @return A response containing the directory info and the status of creating the directory. + * @throws StorageErrorException If the directory has already existed, the parent directory does not exist or directory is an invalid resource name. + */ + public ResponseCode Samples
+ * + *Copy file from source getDirectoryUrl to the {@code filePath}
+ * + * {@codesnippet com.azure.storage.file.fileClient.startCopy#string-map} + * + * @param sourceUrl Specifies the URL of the source file or blob, up to 2 KB in length. + * @param metadata Optional name-value pairs associated with the file as metadata. Metadata names must adhere to the naming rules. + * @see C# identifiers + * @return A response containing the file copy info and the status of copying the file. + */ + public ResponseCode Samples
+ * + *Abort copy file from copy id("someCopyId")
+ * + * {@codesnippet com.azure.storage.file.fileClient.abortCopy#string} + * + * @param copyId Specifies the copy id which has copying pending status associate with it. + * @return A response containing the status of aborting copy the file. + */ + public VoidResponse abortCopy(String copyId) { + return fileAsyncClient.abortCopy(copyId).block(); + } + + /** + * Downloads a file from the system, including its metadata and properties + * + *Code Samples
+ * + *Download the file to current folder.
+ * + * {@codesnippet com.azure.storage.file.fileClient.downloadToFile#string} + * + * @param downloadFilePath The path where store the downloaded file + */ + public void downloadToFile(String downloadFilePath) { + downloadToFile(downloadFilePath, null); + } + + /** + * Downloads a file from the system, including its metadata and properties + * + *Code Samples
+ * + *Download the file from 1024 to 2048 bytes to current folder.
+ * + * {@codesnippet com.azure.storage.file.fileClient.downloadToFile#string-filerange} + * + * @param downloadFilePath The path where store the downloaded file + * @param range Optional byte range which returns file data only from the specified range. + */ + public void downloadToFile(String downloadFilePath, FileRange range) { + fileAsyncClient.downloadToFile(downloadFilePath, range).block(); + } + + /** + * Downloads a file from the system, including its metadata and properties + * + *Code Samples
+ * + *Download the file with its metadata and properties.
+ * + * {@codesnippet com.azure.storage.file.fileClient.downloadWithProperties} + * + * @return A response that only contains headers and response status code + */ + public ResponseCode Samples
+ * + *Download the file from 1024 to 2048 bytes with its metadata and properties and without the contentMD5.
+ * + * {@codesnippet com.azure.storage.file.fileClient.downloadWithProperties#filerange-boolean} + * + * @param range Optional byte range which returns file data only from the specified range. + * @param rangeGetContentMD5 Optional boolean which the service returns the MD5 hash for the range when it sets to true, as long as the range is less than or equal to 4 MB in size. + * @return A response that only contains headers and response status code + */ + public ResponseCode Samples
+ * + *Delete the file
+ * + * {@codesnippet com.azure.storage.file.fileClient.delete} + * + * @return A response that only contains headers and response status code + * @throws StorageErrorException If the directory doesn't exist or the file doesn't exist. + */ + public VoidResponse delete() { + return fileAsyncClient.delete().block(); } - public static FileClientBuilder syncBuilder() { - throw new UnsupportedOperationException(); + /** + * Retrieves the properties of the storage account's file. + * The properties includes file metadata, last modified date, is server encrypted, and eTag. + * + *Code Samples
+ * + *Retrieve file properties
+ * + * {@codesnippet com.azure.storage.file.fileClient.getProperties} + * + * @return Storage file properties + */ + public ResponseIf {@code null} is passed for the httpHeaders it will clear the httpHeaders associated to the file.
+ * + *Code Samples
+ * + *Set the httpHeaders of contentType of "text/plain"
+ * + * {@codesnippet com.azure.storage.file.fileClient.setHttpHeaders#long-filehttpheaders} + * + *Clear the httpHeaders of the file
+ * + * {@codesnippet com.azure.storage.file.fileClient.setHttpHeaders#long-filehttpheaders.clearHttpHeaders} + * + * @param newFileSize New file size of the file + * @param httpHeaders Resizes a file to the specified size. If the specified byte value is less than the current size of the file, then all ranges above the specified byte value are cleared. + * @return Response of the information about the file + * @throws IllegalArgumentException thrown if parameters fail the validation. + */ + public ResponseIf {@code null} is passed for the metadata it will clear the metadata associated to the file.
+ * + *Code Samples
+ * + *Set the metadata to "file:updatedMetadata"
+ * + * {@codesnippet com.azure.storage.file.fileClient.setMetadata#map} + * + *Clear the metadata of the file
+ * + * {@codesnippet com.azure.storage.file.fileClient.setMetadata#map.clearMetadata} + * + * @param metadata Options.Metadata to set on the file, if null is passed the metadata for the file is cleared + * @return information about the file + * @throws StorageErrorException If the file doesn't exist or the metadata contains invalid keys + */ + public ResponseCode Samples
+ * + *Upload "default" to the file.
+ * + * {@codesnippet com.azure.storage.file.fileClient.upload#flux-long} + * + * @param data The data which will upload to the storage file. + * @param length Specifies the number of bytes being transmitted in the request body. When the FileRangeWriteType is set to clear, the value of this header must be set to zero.. + * @return A response that only contains headers and response status code + * @throws StorageErrorException If you attempt to upload a range that is larger than 4 MB, the service returns status code 413 (Request Entity Too Large) + */ + public ResponseCode Samples
+ * + *Upload the file from 1024 to 2048 bytes with its metadata and properties and without the contentMD5.
+ * + * {@codesnippet com.azure.storage.file.fileClient.upload#bytebuf-long-int-filerangewritetype} + * + * @param data The data which will upload to the storage file. + * @param offset Optional starting point of the upload range. It will start from the beginning if it is {@code null} + * @param length Specifies the number of bytes being transmitted in the request body. When the FileRangeWriteType is set to clear, the value of this header must be set to zero. + * @param type You may specify one of the following options: + *Code Samples
+ * + *Upload the file from the source file path.
+ * + * {@codesnippet com.azure.storage.file.fileClient.uploadFromFile#string} + * + * @param uploadFilePath The path where store the source file to upload + */ + public void uploadFromFile(String uploadFilePath) { + uploadFromFile(uploadFilePath, FileRangeWriteType.UPDATE); } - public MonoCode Samples
+ * + *Upload the file from the source file path.
+ * + * {@codesnippet com.azure.storage.file.fileClient.uploadFromFile#string-filerangewritetype} + * + * @param uploadFilePath The path where store the source file to upload + * @param type You may specify one of the following options: + *Code Samples
+ * + *List all ranges for the file client.
+ * + * {@codesnippet com.azure.storage.file.fileClient.listRanges} + * + * @return {@link FileRange ranges} in the files. + */ + public IterableCode Samples
+ * + *List all ranges within the file range from 1KB to 2KB.
+ * + * {@codesnippet com.azure.storage.file.fileClient.listRanges#filerange} + * + * @param range Optional byte range which returns file data only from the specified range. + * @return {@link FileRange ranges} in the files that satisfy the requirements + */ + public IterableCode Samples
+ * + *List all handles for the file client.
+ * + * {@codesnippet com.azure.storage.file.fileClient.listHandles} + * + * @return {@link HandleItem handles} in the files that satisfy the requirements + */ + public IterableCode Samples
+ * + *List 10 handles for the file client.
+ * + * {@codesnippet com.azure.storage.file.fileClient.listHandles#integer} + * + * @param maxResults Optional max number of results returned per page + * @return {@link HandleItem handles} in the file that satisfy the requirements + */ + public IterableCode Samples
+ * + *Force close handles with handles returned by list handles in recursive.
+ * + * {@codesnippet com.azure.storage.file.fileClient.forceCloseHandles#string} + * + * @param handleId Specifies the handle ID to be closed. Use an asterisk ('*') as a wildcard string to specify all handles. + * @return The counts of number of handles closed + */ + public IterableCode Samples
+ * + *Get the share snapshot id.
+ * + * {@codesnippet com.azure.storage.file.fileClient.getShareSnapshotId} + * + * @return The snapshot id which is a unique {@code DateTime} value that identifies the share snapshot to its base share. + */ + public String getShareSnapshotId() { + return fileAsyncClient.getShareSnapshotId(); } } diff --git a/storage/client/file/src/main/java/com/azure/storage/file/FileClientBuilder.java b/storage/client/file/src/main/java/com/azure/storage/file/FileClientBuilder.java index 610466b2aed52..4c130cd9dfd80 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/FileClientBuilder.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/FileClientBuilder.java @@ -3,7 +3,361 @@ package com.azure.storage.file; +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.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.RetryPolicy; +import com.azure.core.http.policy.UserAgentPolicy; +import com.azure.core.implementation.http.policy.spi.HttpPolicyProviders; +import com.azure.core.util.configuration.Configuration; +import com.azure.core.util.configuration.ConfigurationManager; +import com.azure.storage.common.credentials.SASTokenCredential; +import com.azure.storage.common.credentials.SharedKeyCredential; +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.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; + +/** + * This class provides a fluent builder API to help aid the configuration and instantiation of the {@link FileClient FileClients} + * and {@link FileAsyncClient FileAsyncClients}, calling {@link FileClientBuilder#buildClient() buildClient} + * constructs an instance of FileClient and calling {@link FileClientBuilder#buildAsyncClient() buildAsyncClient} + * constructs an instance of FileAsyncClient. + * + *The client needs the endpoint of the Azure Storage File service, name of the share, and authorization credential. + * {@link FileClientBuilder#endpoint(String) endpoint} gives the builder the endpoint and may give the builder the + * {@link FileClientBuilder#shareName(String)}, {@link FileClientBuilder#filePath(String)} and a {@link SASTokenCredential} that authorizes the client.
+ * + *Instantiating a synchronous File Client with SAS token
+ * {@codesnippet com.azure.storage.file.fileClient.instantiation.sastoken} + * + *Instantiating an Asynchronous File Client with SAS token
+ * {@codesnippet com.azure.storage.file.directoryClient.instantiation.sastoken} + * + *If the {@code endpoint} doesn't contain the query parameters to construct a {@code SASTokenCredential} they may + * be set using {@link FileClientBuilder#credential(SASTokenCredential) credential}.
+ * + * {@codesnippet com.azure.storage.file.fileClient.instantiation.credential} + * + * {@codesnippet com.azure.storage.file.fileAsyncClient.instantiation.credential} + * + *Another way to authenticate the client is using a {@link SharedKeyCredential}. To create a SharedKeyCredential + * a connection string from the Storage File service must be used. Set the SharedKeyCredential with + * {@link FileClientBuilder#connectionString(String) connectionString}. If the builder has both a SASTokenCredential and + * SharedKeyCredential the SharedKeyCredential will be preferred when authorizing requests sent to the service.
+ * + *Instantiating a synchronous File Client with connection string.
+ * {@codesnippet com.azure.storage.file.directoryClient.instantiation.connectionstring} + * + *Instantiating an Asynchronous File Client with connection string.
+ * {@codesnippet com.azure.storage.file.directoryAsyncClient.instantiation.connectionstring} + * + * @see FileClient + * @see FileAsyncClient + * @see SASTokenCredential + * @see SharedKeyCredential + */ public class FileClientBuilder { + private static final String ACCOUNT_NAME = "accountname"; + private final List+ * If {@link FileClientBuilder#pipeline(HttpPipeline) pipeline} is set, then the {@code pipeline} and + * {@link FileClientBuilder#endpoint(String) endpoint} are used to create the + * {@link FileAsyncClient client}. All other builder settings are ignored. + *
+ * + * @return A ShareAsyncClient with the options set from the builder. + * @throws NullPointerException If {@code shareName} is {@code null} or the (@code filePath) is {@code null}. + * @throws IllegalArgumentException If neither a {@link SharedKeyCredential} or {@link SASTokenCredential} has been set. + */ + public FileAsyncClient buildAsyncClient() { + Objects.requireNonNull(shareName); + Objects.requireNonNull(filePath); + + if (pipeline != null) { + return new FileAsyncClient(endpoint, pipeline, shareName, filePath, snapshot); + } + + if (sasTokenCredential == null && sharedKeyCredential == null) { + throw new IllegalArgumentException("Credentials are required for authorization"); + } + + // Closest to API goes first, closest to wire goes last. + final List+ * If {@link FileClientBuilder#pipeline(HttpPipeline) pipeline} is set, then the {@code pipeline} and + * {@link FileClientBuilder#endpoint(String) endpoint} are used to create the + * {@link FileClient client}. All other builder settings are ignored. + *
+ * + * @return A FileClient with the options set from the builder. + * @throws NullPointerException If {@code endpoint}, {@code shareName} or {@code filePath} is {@code null}. + * @throws IllegalStateException If neither a {@link SharedKeyCredential} or {@link SASTokenCredential} has been set. + */ + public FileClient buildClient() { + return new FileClient(this.buildAsyncClient()); + } + + /** + * Sets the endpoint for the Azure Storage File instance that the client will interact with. + * + *The first path segment, if the endpoint contains path segments, will be assumed to be the name of the share + * that the client will interact with. Rest of the path segments should be the path of the file. + * It mush end up with the file name if more segments exist.
+ * + *Query parameters of the endpoint will be parsed using {@link SASTokenCredential#fromQuery(String)} in an + * attempt to generate a {@link SASTokenCredential} to authenticate requests sent to the service.
+ * + * @param endpoint The URL of the Azure Storage File instance to send service requests to and receive responses from. + * @return the updated FileClientBuilder object + * @throws IllegalArgumentException If {@code endpoint} is {@code null} or is an invalid URL + */ + public FileClientBuilder endpoint(String endpoint) { + try { + URL fullURL = new URL(endpoint); + this.endpoint = new URL(fullURL.getProtocol() + "://" + fullURL.getHost()); + + // Attempt to get the share name and file path from the URL passed + String[] pathSegments = fullURL.getPath().split("/"); + int length = pathSegments.length; + this.shareName = length >= 2 ? pathSegments[1] : this.shareName; + String[] filePathParams = length >= 3 ? Arrays.copyOfRange(pathSegments, 2, length) : null; + this.filePath = filePathParams != null ? String.join("/", filePathParams) : this.filePath; + + // Attempt to get the SAS token from the URL passed + this.sasTokenCredential = SASTokenCredential.fromQuery(fullURL.getQuery()); + if (this.sasTokenCredential != null) { + this.sharedKeyCredential = null; + } + } catch (MalformedURLException ex) { + throw new IllegalArgumentException("The Azure Storage File endpoint url is malformed."); + } + + return this; + } + + /** + * Sets the {@link SASTokenCredential} used to authenticate requests sent to the File service. + * + * @param credential SAS token credential generated from the Storage account that authorizes requests + * @return the updated FileClientBuilder object + * @throws NullPointerException If {@code credential} is {@code null}. + */ + public FileClientBuilder credential(SASTokenCredential credential) { + this.sasTokenCredential = Objects.requireNonNull(credential); + this.sharedKeyCredential = null; + return this; + } + + /** + * Sets the {@link SharedKeyCredential} used to authenticate requests sent to the File service. + * + * @param credential Shared key credential generated from the Storage account that authorizes requests + * @return the updated ShareClientBuilder object + * @throws NullPointerException If {@code credential} is {@code null}. + */ + public FileClientBuilder credential(SharedKeyCredential credential) { + this.sharedKeyCredential = Objects.requireNonNull(credential); + this.sasTokenCredential = null; + return this; + } + /** + * Creates a {@link SharedKeyCredential} from the {@code connectionString} used to authenticate requests sent to the + * File service. + * + * @param connectionString Connection string from the Access Keys section in the Storage account + * @return the updated FileClientBuilder object + * @throws NullPointerException If {@code connectionString} is {@code null}. + */ + public FileClientBuilder connectionString(String connectionString) { + Objects.requireNonNull(connectionString); + this.sharedKeyCredential = SharedKeyCredential.fromConnectionString(connectionString); + getEndPointFromConnectionString(connectionString); + return this; + } + + private void getEndPointFromConnectionString(String connectionString) { + MapIf {@code pipeline} is set, all other settings are ignored, aside from {@link FileClientBuilder#endpoint(String) endpoint}, + * {@link FileClientBuilder#shareName(String) shareName} @{link FileClientBuilder#filePath(String) filePath}, and {@link FileClientBuilder#snapshot(String) snaphotShot} + * when building clients.
+ * + * @param pipeline The HTTP pipeline to use for sending service requests and receiving responses. + * @return The updated FileClientBuilder object. + * @throws NullPointerException If {@code pipeline} is {@code null}. + */ + public FileClientBuilder pipeline(HttpPipeline pipeline) { + this.pipeline = Objects.requireNonNull(pipeline); + 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 builder, defaults to Configuration.NONE + * @param configuration configuration store + * @return the updated FileClientBuilder object + */ + public FileClientBuilder configuration(Configuration configuration) { + this.configuration = configuration; + return this; + } - // fileUri, SharedKeyCredential, FileClientOptions ,withSnapshot + /** + * Sets the snapshot that the constructed clients will interact with. This snapshot must be linked to the share + * that has been specified in the builder. + * + * @param snapshot Identifier of the snapshot + * @return the updated FileClientBuilder object + * @throws NullPointerException If {@code snapshot} is {@code null}. + */ + public FileClientBuilder snapshot(String snapshot) { + this.snapshot = snapshot; + return this; + } } diff --git a/storage/client/file/src/main/java/com/azure/storage/file/FileConfiguration.java b/storage/client/file/src/main/java/com/azure/storage/file/FileConfiguration.java new file mode 100644 index 0000000000000..02d964e002412 --- /dev/null +++ b/storage/client/file/src/main/java/com/azure/storage/file/FileConfiguration.java @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.storage.file; + +/* + * Gets the SDK information for this library component. + */ +class FileConfiguration { + //TODO: Eventually remove these hardcoded strings with https://github.com/Azure/azure-sdk-for-java/issues/3141 + static final String NAME = "azure-storage-file"; + static final String VERSION = "12.0.0-preview.1"; +} diff --git a/storage/client/file/src/main/java/com/azure/storage/file/FileServiceAsyncClient.java b/storage/client/file/src/main/java/com/azure/storage/file/FileServiceAsyncClient.java index 9c66716ca61c0..3c13197f7d477 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/FileServiceAsyncClient.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/FileServiceAsyncClient.java @@ -3,51 +3,327 @@ package com.azure.storage.file; +import com.azure.core.http.HttpPipeline; import com.azure.core.http.rest.Response; +import com.azure.core.http.rest.SimpleResponse; import com.azure.core.http.rest.VoidResponse; +import com.azure.core.implementation.util.ImplUtils; +import com.azure.core.util.Context; +import com.azure.storage.common.credentials.SASTokenCredential; +import com.azure.storage.common.credentials.SharedKeyCredential; +import com.azure.storage.file.implementation.AzureFileStorageBuilder; +import com.azure.storage.file.implementation.AzureFileStorageImpl; +import com.azure.storage.file.models.CorsRule; +import com.azure.storage.file.models.DeleteSnapshotsOptionType; import com.azure.storage.file.models.FileServiceProperties; +import com.azure.storage.file.models.ListSharesIncludeType; import com.azure.storage.file.models.ListSharesOptions; +import com.azure.storage.file.models.ListSharesResponse; +import com.azure.storage.file.models.ServicesListSharesSegmentResponse; import com.azure.storage.file.models.ShareItem; +import com.azure.storage.file.models.StorageErrorException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import org.reactivestreams.Publisher; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -import java.util.Map; - -public class FileServiceAsyncClient { +/** + * This class provides a azureFileStorageClient that contains all the operations for interacting with a file account in Azure Storage. + * Operations allowed by the azureFileStorageClient are creating, listing, and deleting shares and retrieving and updating properties + * of the account. + * + *Instantiating an Asynchronous File Service Client
+ * + * {@codesnippet com.azure.storage.file.fileServiceAsyncClient.instantiation} + * + *View {@link FileServiceClientBuilder this} for additional ways to construct the azureFileStorageClient.
+ * + * @see FileServiceClientBuilder + * @see FileServiceClient + * @see SharedKeyCredential + * @see SASTokenCredential + */ +public final class FileServiceAsyncClient { + private final AzureFileStorageImpl azureFileStorageClient; - FileServiceAsyncClient() { - throw new UnsupportedOperationException(); + /** + * Creates a FileServiceClient that sends requests to the storage account at {@code endpoint}. + * Each service call goes through the {@code httpPipeline}. + * + * @param endpoint URL for the Storage File service + * @param httpPipeline HttpPipeline that the HTTP requests and responses flow through + */ + FileServiceAsyncClient(URL endpoint, HttpPipeline httpPipeline) { + this.azureFileStorageClient = new AzureFileStorageBuilder().pipeline(httpPipeline) + .url(endpoint.toString()) + .build(); } - public static FileServiceClientBuilder asyncBuilder() { - throw new UnsupportedOperationException(); + /** + * Get the url of the storage file service client. + * @return the url of the Storage File service. + * @throws RuntimeException If the file service is using a malformed URL. + */ + public URL getFileServiceUrl() { + try { + return new URL(azureFileStorageClient.url()); + } catch (MalformedURLException e) { + throw new RuntimeException(String.format("Invalid URL on %s: %s" + getClass().getSimpleName(), + azureFileStorageClient.url()), e); + } } - public String url() { - throw new UnsupportedOperationException(); + /** + * Constructs a ShareAsyncClient that interacts with the specified share. + * + *If the share doesn't exist in the storage account {@link ShareAsyncClient#create() create} in the azureFileStorageClient will + * need to be called before interaction with the share can happen.
+ * + * @param shareName Name of the share + * @return a ShareAsyncClient that interacts with the specified share + */ + public ShareAsyncClient getShareAsyncClient(String shareName) { + return new ShareAsyncClient(azureFileStorageClient, shareName); } - public ShareAsyncClient getShareClient(String shareName) { - throw new UnsupportedOperationException(); + /** + * Lists all shares in the storage account without their metadata or snapshots. + * + *Code Samples
+ * + *List all shares in the account
+ * + * {@codesnippet com.azure.storage.file.fileServiceAsyncClient.listShares} + * + * @return {@link ShareItem Shares} in the storage account without their metadata or snapshots + */ + public FluxSet starts with name filter using {@link ListSharesOptions#prefix(String) prefix} to filter shares that are + * listed.
+ * + *Pass true to {@link ListSharesOptions#includeMetadata(boolean) includeMetadata} to have metadata returned for + * the shares.
+ * + *Pass true to {@link ListSharesOptions#includeSnapshots(boolean) includeSnapshots} to have snapshots of the + * shares listed.
+ * + *Code Samples
+ * + *List all shares that begin with "azure"
+ * + * {@codesnippet com.azure.storage.file.fileServiceAsyncClient.listShares#ListSharesOptions.prefix} + * + *List all shares including their snapshots and metadata
+ * + * {@codesnippet com.azure.storage.file.fileServiceAsyncClient.listShares#ListSharesOptions.metadata.snapshot} + * + * @param options Options for listing shares + * @return {@link ShareItem Shares} in the storage account that satisfy the filter requirements + */ public FluxCode Samples
+ * + *Retrieve File service properties
+ * + * {@codesnippet com.azure.storage.file.fileServiceAsyncClient.getProperties} + * + * @return Storage account File service properties + */ public MonoCode Sample
+ * + *Clear CORS in the File service
+ * + * {@codesnippet com.azure.storage.file.fileServiceAsyncClient.setProperties#fileServiceProperties.clearCORS} + * + *Enable Minute and Hour Metrics
+ * + * {@codesnippet com.azure.storage.file.fileServiceAsyncClient.setProperties#fileServiceProperties} + * + * @param properties Storage account File service properties + * @return A response that only contains headers and response status code + * @throws StorageErrorException When one of the following is true + *Code Samples
+ * + *Create the share "test"
+ * + * {@codesnippet com.azure.storage.file.fileServiceAsyncClient.createShare#string} + * + * @param shareName Name of the share + * @return A response containing the ShareAsyncClient and the status of creating the share. + * @throws StorageErrorException If a share with the same name already exists + */ + public MonoCode Samples
+ * + *Create the share "test" with metadata "share:metadata"
+ * + * {@codesnippet com.azure.storage.file.fileServiceAsyncClient.createShare#string-map-integer.metadata} + * + *Create the share "test" with a quota of 10 GB
+ * + * {@codesnippet com.azure.storage.file.fileServiceAsyncClient.createShare#string-map-integer.quota} + * + * @param shareName Name of the share + * @param metadata Optional metadata to associate with the share + * @param quotaInGB Optional maximum size the share is allowed to grow to in GB. This must be greater than 0 and + * less than or equal to 5120. The default value is 5120. + * @return A response containing the ShareAsyncClient and the status of creating the share. + * @throws StorageErrorException If a share with the same name already exists or {@code quotaInGB} is outside the + * allowed range. + */ + public MonoCode Samples
+ * + *Delete the share "test"
+ * + * {@codesnippet com.azure.storage.file.fileServiceAsyncClient.deleteShare#string} + * + * @param shareName Name of the share + * @return A response that only contains headers and response status code + * @throws StorageErrorException If the share doesn't exist + */ + public MonoCode Samples
+ * + *Delete the snapshot of share "test" that was created at current time.
+ * + * {@codesnippet com.azure.storage.file.fileServiceAsyncClient.deleteShare#string-string} + * + * @param shareName Name of the share + * @param snapshot Identifier of the snapshot + * @return A response that only contains headers and response status code + * @throws StorageErrorException If the share doesn't exist or the snapshot doesn't exist + */ + public MonoInstantiating a Synchronous File Service Client
+ * + * {@codesnippet com.azure.storage.file.fileServiceClient.instantiation} + * + *View {@link FileServiceClientBuilder this} for additional ways to construct the fileServiceAsyncClient.
+ * + * @see FileServiceClientBuilder + * @see FileServiceAsyncClient + * @see SharedKeyCredential + * @see SASTokenCredential + */ +public final class FileServiceClient { + private final FileServiceAsyncClient fileServiceAsyncClient; - private final FileServiceAsyncClient client; + /** + * Creates a FileServiceClient that wraps a FileServiceAsyncClient and blocks requests. + * + * @param client FileServiceAsyncClient that is used to send requests + */ + FileServiceClient(FileServiceAsyncClient client) { + this.fileServiceAsyncClient = client; + } - FileServiceClient() { - throw new UnsupportedOperationException(); + /** + * Get the url of the storage file service client. + * @return the url of the Storage File service. + * @throws RuntimeException If the directory is using a malformed URL. + */ + public URL getFileServiceUrl() { + return fileServiceAsyncClient.getFileServiceUrl(); } - public static FileServiceClientBuilder syncBuilder() { - throw new UnsupportedOperationException(); + /** + * Constructs a ShareClient that interacts with the specified share. + * + *If the share doesn't exist in the storage account {@link ShareClient#create() create} in the fileServiceAsyncClient will + * need to be called before interaction with the share can happen.
+ * + * @param shareName Name of the share + * @return a ShareClient that interacts with the specified share + */ + public ShareClient getShareClient(String shareName) { + return new ShareClient(fileServiceAsyncClient.getShareAsyncClient(shareName)); } - public String url() { - throw new UnsupportedOperationException(); + /** + * Lists all shares in the storage account without their metadata or snapshots. + * + *Code Samples
+ * + *List all shares in the account
+ * + * {@codesnippet com.azure.storage.file.fileServiceClient.listShares} + * + * @return {@link ShareItem Shares} in the storage account without their metadata or snapshots + */ + public IterableSet starts with name filter using {@link ListSharesOptions#prefix(String) prefix} to filter shares that are + * listed.
+ * + *Pass true to {@link ListSharesOptions#includeMetadata(boolean) includeMetadata} to have metadata returned for + * the shares.
+ * + *Pass true to {@link ListSharesOptions#includeSnapshots(boolean) includeSnapshots} to have snapshots of the + * shares listed.
+ * + *Code Samples
+ * + *List all shares that begin with "azure"
+ * + * {@codesnippet com.azure.storage.file.fileServiceClient.listShares#ListSharesOptions.prefix} + * + *List all shares including their snapshots and metadata
+ * + * {@codesnippet com.azure.storage.file.fileServiceClient.listShares#ListSharesOptions.metadata.snapshot} + * + * @param options Options for listing shares + * @return {@link ShareItem Shares} in the storage account that satisfy the filter requirements + */ + public IterableCode Samples
+ * + *Retrieve File service properties
+ * + * {@codesnippet com.azure.storage.file.fileServiceClient.getProperties} + * + * @return Storage account File service properties + */ + public ResponseCode Sample
+ * + *Clear CORS in the File service
+ * + * {@codesnippet com.azure.storage.file.fileServiceClient.setProperties#fileServiceProperties.clearCORS} + * + *Enable Minute and Hour Metrics
+ * + * {@codesnippet com.azure.storage.file.fileServiceClient.setProperties#fileServiceProperties} + * + * @param properties Storage account File service properties + * @return A response that only contains headers and response status code + * @throws StorageErrorException When one of the following is true + *Code Samples
+ * + *Create the share with share name of "myshare"
+ * {@codesnippet com.azure.storage.file.fileServiceClient.createShare#string} + * + * @param shareName Name of the share + * @return A response containing the ShareClient and the status of creating the share. + * @throws StorageErrorException If a share with the same name already exists + */ + public ResponseCode Samples
+ * + *Create the share "test" with metadata "share:metadata"
+ * + * {@codesnippet com.azure.storage.file.fileServiceClient.createShare#string-map-integer.metadata} + * + *Create the share "test" with a quota of 10 GB
+ * + * {@codesnippet com.azure.storage.file.fileServiceClient.createShare#string-map-integer.quota} + * + * @param shareName Name of the share + * @param metadata Optional metadata to associate with the share + * @param quotaInGB Optional maximum size the share is allowed to grow to in GB. This must be greater than 0 and + * less than or equal to 5120. The default value is 5120. + * @return A response containing the ShareClient and the status of creating the share. + * @throws StorageErrorException If a share with the same name already exists or {@code quotaInGB} is outside the + * allowed range. + */ + public ResponseCode Samples
+ * + *Delete the share "test"
+ * + * {@codesnippet com.azure.storage.file.fileServiceClient.deleteShare#string} + * + * @param shareName Name of the share + * @return A response that only contains headers and response status code + * @throws StorageErrorException If the share doesn't exist + */ + public VoidResponse deleteShare(String shareName) { + return deleteShare(shareName, null); } - public MonoCode Samples
+ * + *Delete the snapshot of share "test" that was created at current time.
+ * + * {@codesnippet com.azure.storage.file.fileServiceClient.deleteShare#string-string} + * + * @param shareName Name of the share + * @param snapshot Identifier of the snapshot + * @return A response that only contains headers and response status code + * @throws StorageErrorException If the share doesn't exist or the snapshot doesn't exist + */ + public VoidResponse deleteShare(String shareName, String snapshot) { + return fileServiceAsyncClient.deleteShare(shareName, snapshot).block(); } } diff --git a/storage/client/file/src/main/java/com/azure/storage/file/FileServiceClientBuilder.java b/storage/client/file/src/main/java/com/azure/storage/file/FileServiceClientBuilder.java index 01148e8af57f5..5a6393ffffdec 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/FileServiceClientBuilder.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/FileServiceClientBuilder.java @@ -3,7 +3,309 @@ package com.azure.storage.file; -public class FileServiceClientBuilder { +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.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.RetryPolicy; +import com.azure.core.http.policy.UserAgentPolicy; +import com.azure.core.implementation.http.policy.spi.HttpPolicyProviders; +import com.azure.core.util.configuration.Configuration; +import com.azure.core.util.configuration.ConfigurationManager; +import com.azure.storage.common.credentials.SASTokenCredential; +import com.azure.storage.common.credentials.SharedKeyCredential; +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; - // connection string, FileClientOptions, Uri, SharedKeyCredential +/** + * This class provides a fluent builder API to help aid the configuration and instantiation of the {@link FileServiceClient FileServiceClients} + * and {@link FileServiceAsyncClient FileServiceAsyncClients}, calling {@link FileServiceClientBuilder#buildClient() buildClient} + * constructs an instance of FileServiceClient and calling {@link FileServiceClientBuilder#buildAsyncClient() buildAsyncClient} + * constructs an instance of FileServiceAsyncClient. + * + *The client needs the endpoint of the Azure Storage File service and authorization credential. + * {@link FileServiceClientBuilder#endpoint(String) endpoint} gives the builder the endpoint and may give the builder a + * {@link SASTokenCredential} that authorizes the client.
+ * + *Instantiating a synchronous FileService Client with SAS token
+ * {@codesnippet com.azure.storage.file.fileServiceClient.instantiation.sastoken} + * + *Instantiating an Asynchronous FileService Client with SAS token
+ * {@codesnippet com.azure.storage.file.fileServiceAsyncClient.instantiation.sastoken} + * + *If the {@code endpoint} doesn't contain the query parameters to construct a {@code SASTokenCredential} they may + * be set using {@link FileServiceClientBuilder#credential(SASTokenCredential) credential}.
+ * + * {@codesnippet com.azure.storage.file.fileServiceClient.instantiation.credential} + * + * {@codesnippet com.azure.storage.file.fileServiceAsyncClient.instantiation.credential} + * + *Another way to authenticate the client is using a {@link SharedKeyCredential}. To create a SharedKeyCredential + * a connection string from the Storage File service must be used. Set the SharedKeyCredential with + * {@link FileServiceClientBuilder#connectionString(String) connectionString}. If the builder has both a SASTokenCredential and + * SharedKeyCredential the SharedKeyCredential will be preferred when authorizing requests sent to the service.
+ * + *Instantiating a synchronous FileService Client with connection string.
+ * {@codesnippet com.azure.storage.file.fileServiceClient.instantiation.connectionstring} + * + *Instantiating an Asynchronous FileService Client with connection string.
+ * {@codesnippet com.azure.storage.file.fileServiceAsyncClient.instantiation.connectionstring} + * + * @see FileServiceClient + * @see FileServiceAsyncClient + * @see SASTokenCredential + * @see SharedKeyCredential + */ +public final class FileServiceClientBuilder { + private static final String ACCOUNT_NAME = "accountname"; + private final List+ * If {@link FileServiceClientBuilder#pipeline(HttpPipeline) pipeline} is set, then the {@code pipeline} and + * {@link FileServiceClientBuilder#endpoint(String) endpoint} are used to create the + * {@link FileServiceAsyncClient client}. All other builder settings are ignored. + *
+ * + * @return A FileServiceAsyncClient with the options set from the builder. + * @throws IllegalArgumentException If neither a {@link SharedKeyCredential} or {@link SASTokenCredential} has been set. + */ + public FileServiceAsyncClient buildAsyncClient() { + if (pipeline != null) { + return new FileServiceAsyncClient(endpoint, pipeline); + } + + if (sasTokenCredential == null && sharedKeyCredential == null) { + throw new IllegalArgumentException("Credentials are required for authorization"); + } + + // Closest to API goes first, closest to wire goes last. + final List+ * If {@link FileServiceClientBuilder#pipeline(HttpPipeline) pipeline} is set, then the {@code pipeline} and + * {@link FileServiceClientBuilder#endpoint(String) endpoint} are used to create the + * {@link FileServiceClient client}. All other builder settings are ignored. + *
+ * + * @return A FileServiceClient with the options set from the builder. + * @throws NullPointerException If {@code endpoint} is {@code null}. + * @throws IllegalStateException If neither a {@link SharedKeyCredential} or {@link SASTokenCredential} has been set. + */ + public FileServiceClient buildClient() { + return new FileServiceClient(buildAsyncClient()); + } + + /** + * Sets the endpoint for the Azure Storage File instance that the client will interact with. + * + *Query parameters of the endpoint will be parsed using {@link SASTokenCredential#fromQuery(String) fromQuery} in an + * attempt to generate a {@link SASTokenCredential} to authenticate requests sent to the service.
+ * + * @param endpoint The URL of the Azure Storage File instance to send service requests to and receive responses from. + * @return the updated FileServiceClientBuilder object + * @throws IllegalArgumentException If {@code endpoint} isn't a proper URL + */ + public FileServiceClientBuilder endpoint(String endpoint) { + try { + URL fullURL = new URL(endpoint); + this.endpoint = new URL(fullURL.getProtocol() + "://" + fullURL.getHost()); + + // Attempt to get the SAS token from the URL passed + this.sasTokenCredential = SASTokenCredential.fromQuery(fullURL.getQuery()); + if (this.sasTokenCredential != null) { + this.sharedKeyCredential = null; + } + } catch (MalformedURLException ex) { + throw new IllegalArgumentException("The Azure Storage File Service endpoint url is malformed."); + } + + return this; + } + + /** + * Sets the {@link SASTokenCredential} used to authenticate requests sent to the Queue service. + * + * @param credential SAS token credential generated from the Storage account that authorizes requests + * @return the updated FileServiceClientBuilder object + * @throws NullPointerException If {@code credential} is {@code null}. + */ + public FileServiceClientBuilder credential(SASTokenCredential credential) { + this.sasTokenCredential = Objects.requireNonNull(credential); + this.sharedKeyCredential = null; + return this; + } + + /** + * Sets the {@link SharedKeyCredential} used to authenticate requests sent to the Queue service. + * + * @param credential Shared key credential generated from the Storage account that authorizes requests + * @return the updated FileServiceClientBuilder object + * @throws NullPointerException If {@code credential} is {@code null}. + */ + public FileServiceClientBuilder credential(SharedKeyCredential credential) { + this.sharedKeyCredential = Objects.requireNonNull(credential); + this.sasTokenCredential = null; + return this; + } + + /** + * Creates a {@link SharedKeyCredential} from the {@code connectionString} used to authenticate requests sent to the + * File service. + * + * @param connectionString Connection string from the Access Keys section in the Storage account + * @return the updated FileServiceClientBuilder object + * @throws NullPointerException If {@code connectionString} is {@code null}. + */ + public FileServiceClientBuilder connectionString(String connectionString) { + Objects.requireNonNull(connectionString); + this.sharedKeyCredential = SharedKeyCredential.fromConnectionString(connectionString); + getEndPointFromConnectionString(connectionString); + return this; + } + + private void getEndPointFromConnectionString(String connectionString) { + MapInstantiating an Asynchronous Share Client
+ * + * {@codesnippet com.azure.storage.file.shareAsyncClient.instantiation} + * + *View {@link ShareClientBuilder this} for additional ways to construct the azureFileStorageClient.
+ * + * @see ShareClientBuilder + * @see ShareClient + * @see SharedKeyCredential + * @see SASTokenCredential + */ public class ShareAsyncClient { + private final AzureFileStorageImpl azureFileStorageClient; + private final String shareName; + private final String snapshot; + + /** + * Creates a ShareAsyncClient that sends requests to the storage share at {@link AzureFileStorageImpl#url() endpoint}. + * Each service call goes through the {@link HttpPipeline pipeline} in the {@code azureFileStorageClient}. + * + * @param client Client that interacts with the service interfaces + * @param shareName Name of the share + */ + ShareAsyncClient(AzureFileStorageImpl client, String shareName) { + this.shareName = shareName; + this.snapshot = null; - ShareAsyncClient() { - throw new UnsupportedOperationException(); + this.azureFileStorageClient = client; } - public static ShareClientBuilder asyncBuilder() { - throw new UnsupportedOperationException(); + /** + * Creates a ShareAsyncClient that sends requests to the storage share at {@code endpoint}. + * Each service call goes through the {@code httpPipeline}. + * + * @param endpoint URL for the Storage File service + * @param httpPipeline HttpPipeline that the HTTP requests and response flow through + * @param shareName Name of the share + * @param snapshot Optional specific snapshot of the share + */ + ShareAsyncClient(URL endpoint, HttpPipeline httpPipeline, String shareName, String snapshot) { + this.shareName = shareName; + this.snapshot = snapshot; + + this.azureFileStorageClient = new AzureFileStorageBuilder().pipeline(httpPipeline) + .url(endpoint.toString()) + .build(); } - public String url() { - throw new UnsupportedOperationException(); + /** + * Get the url of the storage share client. + * @return the url of the Storage Share. + * @throws RuntimeException If the share is using a malformed URL. + */ + public URL getShareUrl() { + try { + return new URL(azureFileStorageClient.url()); + } catch (MalformedURLException e) { + throw new RuntimeException(String.format("Invalid URL on %s: %s" + getClass().getSimpleName(), + azureFileStorageClient.url()), e); + } } + + /** + * Constructs a {@link DirectoryAsyncClient} that interacts with the root directory in the share. + * + *If the directory doesn't exist in the share {@link DirectoryAsyncClient#create(Map) create} in the azureFileStorageClient will + * need to be called before interaction with the directory can happen.
+ * + * @return a {@link DirectoryAsyncClient} that interacts with the root directory in the share + */ public DirectoryAsyncClient getRootDirectoryClient() { - throw new UnsupportedOperationException(); + return getDirectoryClient(""); } + /** + * Constructs a {@link DirectoryAsyncClient} that interacts with the specified directory. + * + *If the directory doesn't exist in the share {@link DirectoryAsyncClient#create(Map) create} in the azureFileStorageClient will + * need to be called before interaction with the directory can happen.
+ * + * @param directoryName Name of the directory + * @return a {@link DirectoryAsyncClient} that interacts with the directory in the share + */ public DirectoryAsyncClient getDirectoryClient(String directoryName) { - throw new UnsupportedOperationException(); + return new DirectoryAsyncClient(azureFileStorageClient, shareName, directoryName, snapshot); } - public MonoCode Samples
+ * + *Create the share
+ * + * {@codesnippet com.azure.storage.file.shareAsyncClient.create} + * + * @return A response containing information about the share and the status its creation. + * @throws StorageErrorException If the share already exists with different metadata + */ + public MonoCode Samples
+ * + *Create the share with metadata "share:metadata"
+ * + * {@codesnippet com.azure.storage.file.shareAsyncClient.create#map-integer.metadata} + * + *Create the share with a quota of 10 GB
+ * + * {@codesnippet com.azure.storage.file.shareAsyncClient.create#map-integer.quota} + * + * @param metadata Optional metadata to associate with the share + * @param quotaInGB Optional maximum size the share is allowed to grow to in GB. This must be greater than 0 and + * less than or equal to 5120. The default value is 5120. + * @return A response containing information about the share and the status its creation. + * @throws StorageErrorException If the share already exists with different metadata or {@code quotaInGB} is outside the + * allowed range. + */ + public MonoCode Samples
+ * + *Create a snapshot
+ * + * {@codesnippet com.azure.storage.file.shareAsyncClient.createSnapshot} + * + * @return A response containing information about the snapshot of share. + * @throws StorageErrorException If the share doesn't exist, there are 200 snapshots of the share, or a snapshot is + * in progress for the share + */ + public MonoCode Samples
+ * + *Create a snapshot with metadata "snapshot:metadata"
+ * + * {@codesnippet com.azure.storage.file.shareAsyncClient.createSnapshot#map} + * + * @param metadata Optional metadata to associate with the snapshot. If {@code null} the metadata of the share + * will be copied to the snapshot. + * @return A response containing information about the snapshot of share. + * @throws StorageErrorException If the share doesn't exist, there are 200 snapshots of the share, or a snapshot is + * in progress for the share + */ public MonoCode Samples
+ * + *Delete the share
+ * + * {@codesnippet com.azure.storage.file.shareAsyncClient.delete} + * + * @return A response that only contains headers and response status code + * @throws StorageErrorException If the share doesn't exist + */ + public MonoCode Samples
+ * + *Retrieve the share properties
+ * + * {@codesnippet com.azure.storage.file.shareAsyncClient.getProperties} + * + * @return the properties of the share + * @throws StorageErrorException If the share doesn't exist + */ + public MonoCode Samples
+ * + *Set the quota to 1024 GB
+ * + * {@codesnippet com.azure.storage.file.shareAsyncClient.setQuota} + * + * @param quotaInGB Size in GB to limit the share's growth. The quota in GB must be between 1 and 5120. + * @return information about the share + * @throws StorageErrorException If the share doesn't exist or {@code quotaInGB} is outside the allowed bounds + */ public MonoIf {@code null} is passed for the metadata it will clear the metadata associated to the share.
+ * + *Code Samples
+ * + *Set the metadata to "share:updatedMetadata"
+ * + * {@codesnippet com.azure.storage.file.shareAsyncClient.setMetadata#map} + * + *Clear the metadata of the share
+ * + * {@codesnippet com.azure.storage.file.shareAsyncClient.clearMetadata#map} + * + * @param metadata Metadata to set on the share, if null is passed the metadata for the share is cleared + * @return information about the share + * @throws StorageErrorException If the share doesn't exist or the metadata contains invalid keys + */ public MonoCode Samples
+ * + *List the stored access policies
+ * + * {@codesnippet com.azure.storage.file.shareAsyncClient.getAccessPolicy} + * + * @return The stored access policies specified on the queue. + * @throws StorageErrorException If the share doesn't exist + */ + public FluxCode Samples
+ * + *Set a read only stored access policy
+ * + * {@codesnippet com.azure.storage.file.shareAsyncClient.setAccessPolicy} + * + * @param permissions Access policies to set on the queue + * @return A response that only contains headers and response status code + * @throws StorageErrorException If the share doesn't exist, a stored access policy doesn't have all fields filled out, + * or the share will have more than five policies. + */ public MonoCode Samples
+ * + *Retrieve the storage statistics
+ * + * {@codesnippet com.azure.storage.file.shareAsyncClient.getStatistics} + * + * @return the storage statistics of the share + */ public MonoCode Samples
+ * + *Create the directory "mydirectory"
+ * + * {@codesnippet com.azure.storage.file.shareAsyncClient.createDirectory#string} + * * + * @param directoryName Name of the directory + * @return A response containing a {@link DirectoryAsyncClient} to interact with the created directory and the + * status of its creation. + * @throws StorageErrorException If the share doesn't exist, the directory already exists or is in the process of + * being deleted, or the parent directory for the new directory doesn't exist + */ + public MonoCode Samples
+ * + *Create the directory "documents" with metadata "directory:metadata"
+ * + * {@codesnippet com.azure.storage.file.shareAsyncClient.createDirectory#string-map} + * + * @param directoryName Name of the directory + * @param metadata Optional metadata to associate with the directory + * @return A response containing a {@link DirectoryAsyncClient} to interact with the created directory and the + * status of its creation. + * @throws StorageErrorException If the share doesn't exist, the directory already exists or is in the process of + * being deleted, the parent directory for the new directory doesn't exist, or the metadata is using an illegal + * key name + */ public MonoCode Samples
+ * + *Delete the directory "empty"
+ * + * {@codesnippet com.azure.storage.file.shareAsyncClient.deleteDirectory#string} + * + * @param directoryName Name of the directory + * @return A response that only contains headers and response status code + * @throws StorageErrorException If the share doesn't exist or the directory isn't empty + */ public MonoCode Samples
+ * + *Get the share snapshot id.
+ * + * {@codesnippet com.azure.storage.file.fileAsyncClient.getShareSnapshotId} + * + * @return The snapshot id which is a unique {@code DateTime} value that identifies the share snapshot to its base share. + */ + public String getSnapshotId() { + return this.snapshot; + } + + private ResponseInstantiating a Synchronous Share Client
+ * + * {@codesnippet com.azure.storage.file.shareClient.instantiation} + * + *View {@link ShareClientBuilder this} for additional ways to construct the client.
+ * + * @see ShareClientBuilder + * @see ShareAsyncClient + * @see SharedKeyCredential + * @see SASTokenCredential + */ public class ShareClient { - private final ShareAsyncClient client; - ShareClient() { - throw new UnsupportedOperationException(); + ShareClient(ShareAsyncClient client) { + this.client = client; } - public static ShareClientBuilder syncBuilder() { - throw new UnsupportedOperationException(); - } - - public String url() { - throw new UnsupportedOperationException(); + /** + * Get the url of the storage share client. + * @return the url of the Storage Share. + * @throws RuntimeException If the share is using a malformed URL. + */ + public URL getShareUrl() { + return client.getShareUrl(); } + /** + * Constructs a {@link DirectoryClient} that interacts with the root directory in the share. + * + *If the directory doesn't exist in the share {@link DirectoryClient#create(Map) create} in the client will + * need to be called before interaction with the directory can happen.
+ * + * @return a {@link DirectoryClient} that interacts with the root directory in the share + */ public DirectoryClient getRootDirectoryClient() { - throw new UnsupportedOperationException(); + return getDirectoryClient(""); } + /** + * Constructs a {@link DirectoryClient} that interacts with the specified directory. + * + *If the directory doesn't exist in the share {@link DirectoryClient#create(Map) create} in the client will + * need to be called before interaction with the directory can happen.
+ * + * @param directoryName Name of the directory + * @return a {@link DirectoryClient} that interacts with the directory in the share + */ public DirectoryClient getDirectoryClient(String directoryName) { - throw new UnsupportedOperationException(); + return new DirectoryClient(client.getDirectoryClient(directoryName)); + } + + /** + * Creates the share in the storage account. + * + *Code Samples
+ * + *Create the share
+ * + * {@codesnippet com.azure.storage.file.shareClient.create} + * + * @return A response containing information about the share and the status its creation. + * @throws StorageErrorException If the share already exists with different metadata + */ + public ResponseCode Samples
+ * + *Create the share with metadata "share:metadata"
+ * + * {@codesnippet com.azure.storage.file.shareClient.create#map-integer.metadata} + * + *Create the share with a quota of 10 GB
+ * + * {@codesnippet com.azure.storage.file.shareClient.create#map-integer.quota} + * + * @param metadata Optional metadata to associate with the share + * @param quotaInGB Optional maximum size the share is allowed to grow to in GB. This must be greater than 0 and + * less than or equal to 5120. The default value is 5120. + * @return A response containing information about the share and the status its creation. + * @throws StorageErrorException If the share already exists with different metadata or {@code quotaInGB} is outside the + * allowed range. + */ + public ResponseCode Samples
+ * + *Create a snapshot
+ * + * {@codesnippet com.azure.storage.file.shareClient.createSnapshot} + * + * @return A response containing information about the snapshot of share. + * @throws StorageErrorException If the share doesn't exist, there are 200 snapshots of the share, or a snapshot is + * in progress for the share + */ + public ResponseCode Samples
+ * + *Create a snapshot with metadata "snapshot:metadata"
+ * + * {@codesnippet com.azure.storage.file.shareClient.createSnapshot#map} + * + * @param metadata Optional metadata to associate with the snapshot. If {@code null} the metadata of the share + * will be copied to the snapshot. + * @return A response containing information about the snapshot of share. + * @throws StorageErrorException If the share doesn't exist, there are 200 snapshots of the share, or a snapshot is + * in progress for the share + */ + public Response