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 @@ + diff --git a/eng/spotbugs-aggregate-report/pom.xml b/eng/spotbugs-aggregate-report/pom.xml index f390bb0c7db4c..7e86db80baad6 100644 --- a/eng/spotbugs-aggregate-report/pom.xml +++ b/eng/spotbugs-aggregate-report/pom.xml @@ -30,6 +30,7 @@ 4.0.0-preview.1 5.0.0-preview.2 12.0.0-preview.1 + 12.0.0-preview.1 12.0.0-preview.1 @@ -183,6 +184,12 @@ + + + com.azure + azure-storage-file + ${azure-storage-file.version} + com.azure azure-storage-queue diff --git a/pom.client.xml b/pom.client.xml index e833ab1290e4e..a981374208bac 100644 --- a/pom.client.xml +++ b/pom.client.xml @@ -393,6 +393,10 @@ Azure Storage - Blobs com.azure.storage.blob* + + Azure Storage - Files + com.azure.storage.file* + Azure Storage - Queues com.azure.storage.queue* @@ -753,6 +757,7 @@ ./sdk/identity/azure-identity ./storage/client/blob + ./storage/client/file ./storage/client/queue diff --git a/sdk/keyvault/azure-keyvault-secrets/src/main/java/com/azure/security/keyvault/secrets/KeyVaultErrorCodeStrings.java b/sdk/keyvault/azure-keyvault-secrets/src/main/java/com/azure/security/keyvault/secrets/KeyVaultErrorCodeStrings.java index 7abc270a6108e..c8932bd0e26b8 100644 --- a/sdk/keyvault/azure-keyvault-secrets/src/main/java/com/azure/security/keyvault/secrets/KeyVaultErrorCodeStrings.java +++ b/sdk/keyvault/azure-keyvault-secrets/src/main/java/com/azure/security/keyvault/secrets/KeyVaultErrorCodeStrings.java @@ -45,4 +45,3 @@ private static synchronized void loadProperties() { } - diff --git a/storage/client/blob/src/samples/java/FileTransferExample.java b/storage/client/blob/src/samples/java/FileTransferExample.java index ff3b9376bfc50..cfd281c1e3f8c 100644 --- a/storage/client/blob/src/samples/java/FileTransferExample.java +++ b/storage/client/blob/src/samples/java/FileTransferExample.java @@ -9,7 +9,6 @@ import java.io.File; import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; import java.net.URL; @@ -139,7 +138,7 @@ private static File createTempEmptyFile(String fileName) throws IOException { } } - private static void createTempFileWithFileSize(File f, long size) throws FileNotFoundException, IOException { + private static void createTempFileWithFileSize(File f, long size) throws IOException { RandomAccessFile raf = new RandomAccessFile(f, "rw"); raf.setLength(size); raf.close(); @@ -148,7 +147,7 @@ private static void createTempFileWithFileSize(File f, long size) throws FileNot private static void checkTwoFilesAreTheSame(File f1, File f2) throws IOException, NoSuchAlgorithmException { String checksumUpload = getFileChecksum(f1); String checksumDownload = getFileChecksum(f2); - if (checksumUpload.equals(checksumDownload)) { + if (!checksumUpload.equals(checksumDownload)) { throw new RuntimeException("The file upload does not match the file download."); } } diff --git a/storage/client/file/README.md b/storage/client/file/README.md new file mode 100644 index 0000000000000..db523e4d3e440 --- /dev/null +++ b/storage/client/file/README.md @@ -0,0 +1,478 @@ +# Azure File client library for Java +The Server Message Block (SMB) protocol is the preferred file share protocol used on-premises today. +The Microsoft Azure File service enables customers to leverage the availability and scalability of Azure’s Cloud Infrastructure as a Service (IaaS) SMB without having to rewrite SMB client applications. + +Files stored in Azure File service shares are accessible via the SMB protocol, and also via REST APIs. +The File service offers the following four resources: the storage account, shares, directories, and files. +Shares provide a way to organize sets of files and also can be mounted as an SMB file share that is hosted in the cloud. + +[Source code][source_code] | [Package (Maven)][package] | [API reference documentation][api_documentation] | [Product documentation][azconfig_docs] + +## Getting started + +### Prerequisites + +- [Java Development Kit (JDK)][jdk] with version 8 or above +- [Azure Subscription][azure_subscription] +- [Create Strorage Account][storage_account] + +### Adding the package to your product + +```xml + + com.azure + azure-storage-file + 12.0.0-preview.1 + +``` + +### Create a Storage Account +To create a Storage Account you can use the Azure Portal or [Azure CLI][azure_cli]. + +```Powershell +az group create \ + --name storage-resource-group \ + --location westus +``` + +### Authenticate the client + +In order to interact with the Storage service (File Service, Share, Directory, MessageId, File) you'll need to create an instance of the Service Client class. +To make this possible you'll need the Account SAS (shared access signature) string of Storage account. Learn more at [SAS Token][sas_token] + +#### Get Credentials + +- **SAS Token** + +a. Use the [Azure CLI][azure_cli] snippet below to get the SAS token from the Storage account. + +```Powershell +az storage file generate-sas + --name {account name} + --expiry {date/time to expire SAS token} + --permission {permission to grant} + --connection-string {connection string of the storage account} +``` + +```Powershell +CONNECTION_STRING= + +az storage file generate-sas + --name javasdksas + --expiry 2019-06-05 + --permission rpau + --connection-string $CONNECTION_STRING +``` +b. Alternatively, get the Account SAS Token from the Azure Portal. +``` +Go to your storage account -> Shared access signature -> Click on Generate SAS and connection string +``` + +- **Shared Key Credential** + +a. Use account name and account key. Account name is your storage account name. +``` +// Here is where we get the key +Go to your storage account -> Access keys -> Key 1/ Key 2 -> Key +``` +b. Use the connection string +``` +// Here is where we get the key +Go to your storage account -> Access Keys -> Keys 1/ Key 2 -> Connection string +``` +## Key concepts +### URL format +Files are addressable using the following URL format: +``` +https://.file.core.windows.net/ +``` +The following URL addresses a queue in the diagram: +``` +https://myaccount.file.core.windows.net/images-to-download +``` + +#### Resource URI Syntax +For the storage account, the base URI for queue operations includes the name of the account only: +``` +https://myaccount.file.core.windows.net +``` +For file, the base URI includes the name of the account and the name of the directory/file: +``` +https://myaccount.file.core.windows.net/myshare/mydirectorypath/myfile +``` + +### Handling Exceptions +```java +TODO +``` + +### Resource Names +The URI to reference a share, directory or file must be unique. Within a given storage account, every share must have a unique name. Every file within a given share or directory must also have a unique name within that share or directory. + +If you attempt to create a share, directory, or file with a name that violates naming rules, the request will fail with status code 400 (Bad Request). + +### Share Names +The rules for File service share names are more restrictive than what is prescribed by the SMB protocol for SMB share names, so that the Blob and File services can share similar naming conventions for containers and shares. The naming restrictions for shares are as follows: + +1. A share name must be a valid DNS name. +1. Share names must start with a letter or number, and can contain only letters, numbers, and the dash (-) character. +1. Every dash (-) character must be immediately preceded and followed by a letter or number; consecutive dashes are not permitted in share names. +1. All letters in a share name must be lowercase. +1. Share names must be from 3 through 63 characters long. + +### Directory and File Names +The Azure File service naming rules for directory and file names are as follows: + +1. Directory and file names are case-preserving and case-insensitive. +1. Directory and file component names must be no more than 255 characters in length. +1. Directory names cannot end with the forward slash character (/). If provided, it will be automatically removed. +1. File names must not end with the forward slash character (/). +1. Reserved URL characters must be properly escaped. +1. The following characters are not allowed: " \ / : | < > * ? +1. Illegal URL path characters not allowed. Code points like \uE000, while valid in NTFS filenames, are not valid Unicode characters. In addition, some ASCII or Unicode characters, like control characters (0x00 to 0x1F, \u0081, etc.), are also not allowed. For rules governing Unicode strings in HTTP/1.1 see [RFC 2616, Section 2.2: Basic Rules][RFC_URL_1] and [RFC 3987][RFL_URL_2]. +1. The following file names are not allowed: LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, PRN, AUX, NUL, CON, CLOCK$, dot character (.), and two dot characters (..). + +### Metadata Names +Metadata for a share or file resource is stored as name-value pairs associated with the resource. Directories do not have metadata. Metadata names must adhere to the naming rules for [C# identifiers][C_identifiers]. + +Note that metadata names preserve the case with which they were created, but are case-insensitive when set or read. If two or more metadata headers with the same name are submitted for a resource, the Azure File service returns status code 400 (Bad Request). + +### File Services +The File Service REST API provides operations on accounts and manage file service properties. It allows the operations of listing and deleting shares, getting and setting file service properties. +Once you have the SASToken, you can construct the file service client with `${accountName}`, `${sasToken}` + +``` +String fileServiceURL = String.format("https://%s.file.core.windows.net", accountName); +FileServiceClient fileServiceClient = new FileServiceClientBuilder().endpoint(fileServiceURL) + .credential(sasToken).buildClient(); +``` + +### Share +The share resource includes metadata and properties for that share. It allows the opertions of creating, creating snapshot, deleting shares, getting share properties, setting metadata, getting and setting ACL (Access policy). +Once you have the SASToken, you can construct the file service client with `${accountName}`, `${shareName}`, `${sasToken}` + +``` +String shareURL = String.format("https://%s.file.core.windows.net", accountName); +ShareClient shareClient = new ShareClientBuilder().endpoint(shareURL) + .credential(sasToken).shareName(shareName).buildClient(); +``` + +### Directory + The directory resource includes the properties for that directory. It allows the operations of creating, listing, deleting directories or subdirectories or files, getting properties, setting metadata, listing and force closing the handles. + Once you have the SASToken, you can construct the file service client with `${accountName}`, `${shareName}`, `${directoryPath}`, `${sasToken}` + + ``` + String directoryURL = String.format("https://%s.file.core.windows.net/%s%s", accountName, shareName, directoryPath, sasToken); + DirectoryClient directoryClient = new DirectoryClientBuilder().endpoint(directoryURL) + .credential(sasToken).shareName(shareName).directoryName(directoryPath).buildClient(); + ``` +### File + The file resource includes the properties for that file. It allows the operations of creating, uploading, copying, downloading, deleting files or range of the files, getting properties, setting metadata, listing and force closing the handles. + Once you have the SASToken, you can construct the file service client with `${accountName}`, `${shareName}`, `${directoryPath}`, `${fileName}`, `${sasToken}` + + ``` + String fileURL = String.format("https://%s.file.core.windows.net", accountName); + FileClient fileClient = new FileClientBuilder().endpoint(fileURL) + .credential(sasToken).shareName(shareName).filePath(directoryPath + "/" + fileName).buildClient(); + ``` + +## Examples + +The following sections provide several code snippets covering some of the most common Configuration Service tasks, including: +- [Create a Share](#Create-a-share) +- [Create a snapshot on Share](#Create-a-snapshot-on-share) +- [Create a Directory](#Create-a-directory) +- [Create a Subdirectory](#Create-a-subdirectory) +- [Create a File](#Create-a-file) +- [List all Shares](#List-all-shares) +- [List all Subdirectories and Files](#List-all-subdirectories-and-files) +- [List all ranges on file](#List-all-ranges-on-file) +- [Delete a Share](#Delete-a-share) +- [Delete a Directory](#Delete-a-directory) +- [Delete a Subdirectory](#Delete-a-subdirectory) +- [Delete a File](#Delete-a-file) +- [Copy a File](#Copy-a-file) +- [Abort copy a File](#Abort-copy-a-file) +- [Upload data to Storage File](#Upload-data-to-storage) +- [Upload file to Storage File](#Upload-file-to-storage) +- [Download data from Storage File](#Download-data-from-storage) +- [Download file from Storage File](#Download-file-from-storage) +- [Get a File Service property](#Get-a-file-service-property) +- [Set a File Service property](#set-a-file-service-property) +- [Set a Share metadata](#Set-a-share-metadata) +- [Get a Share access policy](#Get-a-share-access-policy) +- [Set a Share access policy](#Set-a-share-access-policy) +- [Get handles on Directory and File](#Get-handles-on-directory-file) +- [Force close handles on handle id](#Force-close-handles-on-handle-id) +- [Set quota on Share](#Set-quota-on-share) +- [Set file httpHeaders](#Set-file-httpheaders) + +### Create a share +Create a share in the Storage Account. Throws StorageErrorException If the share fails to be created. +Taking a FileServiceClient in KeyConcept, [`${fileServiceClient}`](#File-services) . + +```Java +String shareName = "testshare"; +fileServiceClient.createShare(shareName); +``` + +### Create a snapshot on Share +Taking a FileServiceClient in KeyConcept, [`${fileServiceClient}`](#File-services) . + +```Java +String shareName = "testshare"; +ShareClient shareClient = fileServiceClient.getShareClient(shareName); +shareClient.createSnapshot(); +``` + +### Create a directory +Taking the [`${shareClient}](#Create-snapshot-on-share) initialized above, [`${shareClient}`](#Share) . + +```Java +String dirName = "testdir"; +shareClient.createDirectory(dirName); +``` + +### Create a subdirectory +Taking the directoryClient in KeyConcept, [`${directoryClient}`](#Directory) . + +```Java +String subDirName = "testsubdir"; +directoryClient.createSubDirectory(subDirName); +``` + +### Create a File +Taking the directoryClient in KeyConcept, [`${directoryClient}`](#Directory) . + +```Java +String fileName = "testfile"; +directoryClient.createFile(fileName); +``` + +### List all Shares +Taking the fileServiceClient in KeyConcept, [`${fileServiceClient}`](#File-services) + +```Java +fileServiceClient.listShares(); +``` + +### Create all subdirectories and files +Taking the directoryClient in KeyConcept, [`${directoryClient}`](#Directory) + +```Java +directoryClient.listFilesAndDirectories(); +``` + +### List all ranges on file +Taking the fileClient in KeyConcept, [`${fileClient}`](#File) + +```Java +fileClient.listRanges(); +``` + +### Delete a share +Taking the shareClient in KeyConcept, [`${shareClient}`](#Share) + +```Java +shareClient.delete(); +``` + +### Delete a directory +Taking the shareClient in KeyConcept, [`${shareClient}`](#Share) . + +```Java +String dirName = "testdir"; +shareClient.deleteDirectory(dirName) +``` + +### Delete a subdirectory +Taking the directoryClient in KeyConcept, [`${directoryClient}`](#Directory) . + +```Java +String subDirName = "testsubdir"; +directoryClient.deleteSubDirectory(subDirName) +``` + +### Delete a file +Taking the directoryClient in KeyConcept, [`${directoryClient}`](#Directory) . + +```Java +String fileName = "testfile"; +directoryClient.deleteFile(fileName) +``` + +### Copy a file +Taking the fileClient in KeyConcept, [`${fileClient}`](#File) with string of source URL. + +```Java +String sourceURL = "https://myaccount.file.core.windows.net/myshare/myfile"; +Response copyInfoResponse = fileClient.startCopy(sourceURL, null); +``` + +### Abort copy a file +Taking the fileClient in KeyConcept, [`${fileClient}`](#File) with the copy info response returned above `${copyId}=[copyInfoResponse](#Copy-a-file)`. + +```Java +String copyId = copyInfoResponse.value().copyId(); +fileClient.abortCopy(copyId); +``` + +### Upload data to storage +Taking the fileClient in KeyConcept, [`${fileClient}`](#File) with data of "default" . + +```Java +ByteBuf data = Unpooled.wrappedBuffer("default".getBytes(StandardCharsets.UTF_8)); +fileClient.upload(data, data.readableBytes()); +``` + +### Upload file to storage +Taking the fileClient in KeyConcept, [`${fileClient}`](#File) . +```Java +String filePath = "/mydir/myfile"; +fileClient.uploadFromFile(filePath); +``` + +### Download data from file range +Taking the fileClient in KeyConcept, [`${fileClient}`](#File) with the range from 1024 to 2048. +```Java +FileRange fileRange = new FileRange(1024, 2047); +fileClient.downloadWithProperties(fileRange, false); +``` + +### Download file from storage +Taking the fileClient in KeyConcept, [`${fileClient}`](#File) and download to the file of filePath. +```Java +String filePath = "/mydir/myfile"; +fileClient.downloadToFile(filePath); +``` + +### Get a file service properties +Taking a FileServiceClient in KeyConcept, [`${fileServiceClient}`](#File-services) . + +```Java +fileServiceClient.getProperties(); +``` + +### Set a file service properties +Taking a FileServiceClient in KeyConcept, [`${fileServiceClient}`](#File-services) . + +```Java +FileServiceProperties properties = fileServiceClient.getProperties().value(); + +properties.minuteMetrics().enabled(true); +properties.hourMetrics().enabled(true); + +VoidResponse response = fileServiceClient.setProperties(properties); +``` + +### Set a share metadata +Taking the shareClient in KeyConcept, [`${shareClient}`](#Share) . + +```Java +Map metadata = Collections.singletonMap("directory", "metadata"); +shareClient.setMetadata(metadata); +``` + +### Get a share access policy +Taking the shareClient in KeyConcept, [`${shareClient}`](#Share) + +```Java +shareClient.getAccessPolicy(); +``` + +### Set a share access policy +Taking the shareClient in KeyConcept, [`${shareClient}`](#Share) . + +```Java +AccessPolicy accessPolicy = new AccessPolicy().permission("r") + .start(OffsetDateTime.now(ZoneOffset.UTC)) + .expiry(OffsetDateTime.now(ZoneOffset.UTC).plusDays(10)); + +SignedIdentifier permission = new SignedIdentifier().id("mypolicy").accessPolicy(accessPolicy); +shareClient.setAccessPolicy(Collections.singletonList(permission)); +``` + +### Get handles on directory file +Taking the directoryClient in KeyConcept, [`${directoryClient}`](#Directory) + +```Java +Iterable handleItems = directoryClient.getHandles(null, true); +``` + +### Force close handles on handle id +Taking the directoryClient in KeyConcept, [`${directoryClient}`](#Directory) and the handle id returned above `${handleId}=[handleItems](#Get-handles-on-directory-file)` + +```Java +String handleId = result.iterator().next().handleId(); +directoryClient.forceCloseHandles(handleId); +``` + +### Set quota on share +Taking the shareClient in KeyConcept, [`${shareClient}`](#Share) . + +```Java +int quotaOnGB = 1; +shareClient.setQuota(quotaOnGB); +``` + +### Set file httpheaders +Taking the fileClient in KeyConcept, [`${fileClient}`](#File) . + +```Java +FileHTTPHeaders httpHeaders = new FileHTTPHeaders().fileContentType("text/plain"); +fileClient.setHttpHeaders(httpHeaders); +``` + +## Troubleshooting + +## General + +When you interact with file using this Java client library, errors returned by the service correspond to the same HTTP status codes returned for [REST API][storage_file_rest] requests. For example, if you try to retrieve a share that doesn't exist in your Storage Account, a `404` error is returned, indicating `Not Found`. + +## Next steps + +### More Samples +- [FileServiceSample](src/samples/java/file/FileServiceSample.java) +- [ShareSample](src/samples/java/file/ShareSample.java) +- [DirectorySample](src/samples/java/file/DirectorySample.java) +- [FileSample](src/samples/java/file/FileSample.java) +- [AsyncSample](src/samples/java/file/AsyncSample.java) + +[Quickstart: Create a Java Spring app with App Configuration](https://docs.microsoft.com/en-us/azure/azure-app-configuration/quickstart-java-spring-app) + +## Contributing +This project welcomes contributions and suggestions. Most contributions require you to agree to a +Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us +the rights to use your contribution. For details, visit https://cla.microsoft.com. + +When you submit a pull request, a CLA-bot will automatically determine whether you need to provide +a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions +provided by the bot. You will only need to do this once across all repos using our CLA. + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or +contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. + +If you would like to become an active contributor to this project please follow the instructions provided in [Microsoft Azure Projects Contribution Guidelines](http://azure.github.io/guidelines.html). + +1. Fork it +2. Create your feature branch (`git checkout -b my-new-feature`) +3. Commit your changes (`git commit -am 'Add some feature'`) +4. Push to the branch (`git push origin my-new-feature`) +5. Create new Pull Request + + +[source_code]: to-be-continue +[package]: to-be-continue +[api_documentation]: https://docs.microsoft.com/en-us/rest/api/storageservices/file-service-rest-api +[storage_docs]: https://docs.microsoft.com/en-us/azure/storage/files/storage-files-introduction +[jdk]: https://docs.microsoft.com/en-us/java/azure/java-supported-jdk-runtime?view=azure-java-stable +[maven]: https://maven.apache.org/ +[azure_subscription]: https://azure.microsoft.com/en-us/free/ +[storage_account]: https://docs.microsoft.com/en-us/azure/storage/common/storage-quickstart-create-account?tabs=azure-portal +[azure_cli]: https://docs.microsoft.com/cli/azure +[sas_token]: https://docs.microsoft.com/en-us/azure/storage/common/storage-dotnet-shared-access-signature-part-1 +[RFC_URL_1]: https://www.ietf.org/rfc/rfc2616.txt +[RFL_URL_2]: https://www.ietf.org/rfc/rfc3987.txt +[C_identifiers]: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/ +[storage_file_rest]: https://docs.microsoft.com/en-us/rest/api/storageservices/file-service-error-codes diff --git a/storage/client/file/pom.xml b/storage/client/file/pom.xml new file mode 100644 index 0000000000000..5355d42110408 --- /dev/null +++ b/storage/client/file/pom.xml @@ -0,0 +1,75 @@ + + + + com.azure + azure-client-sdk-parent + 1.1.0 + ../../../pom.client.xml + + + 4.0.0 + + com.azure + azure-storage-file + 12.0.0-preview.1 + + azure-storage-file + https://github.com/Azure/azure-sdk-for-java + + + + azure-java-build-docs + ${site.url}/site/${project.artifactId} + + + + + scm:git:https://github.com/Azure/azure-sdk-for-java + scm:git:git@github.com:Azure/azure-sdk-for-java.git + HEAD + + + + + com.azure + azure-core + 1.0.0-preview.2 + + + + + com.google.code.findbugs + jsr305 + 3.0.2 + provided + + + + com.azure + azure-core-test + 1.0.0-preview.2 + test + + + com.azure + azure-identity + 1.0.0-preview.1 + test + + + junit + junit + test + + + io.projectreactor + reactor-test + test + + + + diff --git a/storage/client/file/src/main/java/com/azure/storage/common/credentials/SharedKeyCredential.java b/storage/client/file/src/main/java/com/azure/storage/common/credentials/SharedKeyCredential.java index 19b2b4c307221..6e72a9c3d2fe5 100644 --- a/storage/client/file/src/main/java/com/azure/storage/common/credentials/SharedKeyCredential.java +++ b/storage/client/file/src/main/java/com/azure/storage/common/credentials/SharedKeyCredential.java @@ -4,6 +4,7 @@ package com.azure.storage.common.credentials; import com.azure.core.implementation.util.ImplUtils; +import com.azure.core.util.logging.ClientLogger; import io.netty.handler.codec.http.QueryStringDecoder; import javax.crypto.Mac; @@ -26,11 +27,12 @@ * SharedKey credential policy that is put into a header to authorize requests. */ public final class SharedKeyCredential { + private final ClientLogger logger = new ClientLogger(SASTokenCredential.class); private static final String AUTHORIZATION_HEADER_FORMAT = "SharedKey %s:%s"; // Pieces of the connection string that are needed. - private static final String ACCOUNT_NAME = "AccountName".toLowerCase(); - private static final String ACCOUNT_KEY = "AccountKey".toLowerCase(); + private static final String ACCOUNT_NAME = "accountname"; + private static final String ACCOUNT_KEY = "accountkey"; private final String accountName; private final byte[] accountKey; @@ -59,7 +61,7 @@ public static SharedKeyCredential fromConnectionString(String connectionString) HashMap connectionStringPieces = new HashMap<>(); for (String connectionStringPiece : connectionString.split(";")) { String[] kvp = connectionStringPiece.split("=", 2); - connectionStringPieces.put(kvp[0].toLowerCase(), kvp[1]); + connectionStringPieces.put(kvp[0].toLowerCase(Locale.ROOT), kvp[1]); } String accountName = connectionStringPieces.get(ACCOUNT_NAME); @@ -98,9 +100,13 @@ public String generateAuthorizationHeader(URL requestURL, String httpMethod, Map * * @param stringToSign The UTF-8-encoded string to sign. * @return A {@code String} that contains the HMAC-SHA256-encoded signature. - * @throws InvalidKeyException If the accountKey is not a valid Base64-encoded string. + * @throws RuntimeException for one of the following cases: + *
    + *
  • If the HMAC-SHA256 signature for {@code sharedKeyCredentials} fails to generate.
  • + *
  • If the an invalid key has been given to the client.
  • + *
*/ - 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, MapSample Code

+ *

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: + *
    + *
  • There is only one null value for retryDelay and maxRetryDelay.
  • + *
  • Unrecognized retry policy type.
  • + *
*/ public RequestRetryOptions(RetryPolicyType retryPolicyType, Integer maxTries, Integer tryTimeout, Long retryDelayInMs, Long maxRetryDelayInMs, String secondaryHost) { diff --git a/storage/client/file/src/main/java/com/azure/storage/common/policy/RequestRetryPolicy.java b/storage/client/file/src/main/java/com/azure/storage/common/policy/RequestRetryPolicy.java index b862b76928af0..774a44999ce76 100644 --- a/storage/client/file/src/main/java/com/azure/storage/common/policy/RequestRetryPolicy.java +++ b/storage/client/file/src/main/java/com/azure/storage/common/policy/RequestRetryPolicy.java @@ -30,6 +30,11 @@ public final class RequestRetryPolicy implements HttpPipelinePolicy { private final RequestRetryOptions requestRetryOptions; + /** + * Constructs the policy using the retry options. + * + * @param requestRetryOptions Retry options for the policy. + */ public RequestRetryPolicy(RequestRetryOptions requestRetryOptions) { this.requestRetryOptions = requestRetryOptions; } diff --git a/storage/client/file/src/main/java/com/azure/storage/file/DirectoryAsyncClient.java b/storage/client/file/src/main/java/com/azure/storage/file/DirectoryAsyncClient.java index 0669d18eb92f9..c792bdd89d94c 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/DirectoryAsyncClient.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/DirectoryAsyncClient.java @@ -3,77 +3,490 @@ 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.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.DirectoryInfo; import com.azure.storage.file.models.DirectoryProperties; +import com.azure.storage.file.models.DirectorySetMetadataInfo; +import com.azure.storage.file.models.DirectorysCreateResponse; +import com.azure.storage.file.models.DirectorysForceCloseHandlesResponse; +import com.azure.storage.file.models.DirectorysGetPropertiesResponse; +import com.azure.storage.file.models.DirectorysListFilesAndDirectoriesSegmentResponse; +import com.azure.storage.file.models.DirectorysListHandlesResponse; +import com.azure.storage.file.models.DirectorysSetMetadataResponse; import com.azure.storage.file.models.FileHTTPHeaders; import com.azure.storage.file.models.FileRef; import com.azure.storage.file.models.HandleItem; +import com.azure.storage.file.models.StorageErrorException; +import java.net.MalformedURLException; +import java.net.URL; +import java.time.OffsetDateTime; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -import java.util.Map; - +/** + * This class provides a client that contains all the operations for interacting with directory in Azure Storage File Service. + * Operations allowed by the client are creating, deleting and listing subdirectory and file, retrieving properties, setting metadata + * and list or force close handles of the directory or file. + * + *

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 Mono> create() { + return create(null); + } + + /** + * Creates a directory in the file share and returns a response of DirectoryInfo to interact with it. + * + *

Code 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 Mono> create(Map metadata) { - throw new UnsupportedOperationException(); + return azureFileStorageClient.directorys().createWithRestResponseAsync(shareName, directoryPath, null, metadata, Context.NONE) + .map(this::createWithRestResponse); } + /** + * Deletes the directory in the file share. + * + *

Code 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 Mono delete() { - throw new UnsupportedOperationException(); + return azureFileStorageClient.directorys().deleteWithRestResponseAsync(shareName, directoryPath, Context.NONE).map(VoidResponse::new) + .map(VoidResponse::new); + } + + /** + * 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.directoryAsyncClient.getProperties} + * + * @return Storage directory properties + */ + public Mono> getProperties() { + return azureFileStorageClient.directorys().getPropertiesWithRestResponseAsync(shareName, directoryPath, snapshot, null, Context.NONE) + .map(this::getPropertiesResponse); } - public Mono> getProperties(String shareSnapshot) { - throw new UnsupportedOperationException(); + /** + * Sets the user-defined metadata to associate to the directory. + * + *

If {@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 Mono> setMetadata(Map metadata) { + return azureFileStorageClient.directorys().setMetadataWithRestResponseAsync(shareName, directoryPath, null, metadata, Context.NONE) + .map(this::setMetadataResponse); } - public Mono> setMetadata(Map metadata) { - throw new UnsupportedOperationException(); + /** + * Lists all sub-directories and files in this directory without their prefix or maxResult. + * + *

Code 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 Flux listFilesAndDirectories() { + return listFilesAndDirectories(null, null); } - public Flux listFilesAndDirectories(String prefix, int maxResults, String shareSnapshot) { - throw new UnsupportedOperationException(); + /** + * Lists all sub-directories and files in this directory with their prefix or snapshots. + * + *

Code 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 Flux listFilesAndDirectories(String prefix, Integer maxResults) { + return azureFileStorageClient.directorys().listFilesAndDirectoriesSegmentWithRestResponseAsync(shareName, directoryPath, prefix, snapshot, null, maxResults, null, Context.NONE) + .flatMapMany(response -> nextPageForFileAndDirecotries(response, prefix, maxResults)); } - public Flux getHandles(int maxResult, boolean recursive) { - throw new UnsupportedOperationException(); + /** + * List of open handles on a directory or a file. + * + *

Code 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 Flux getHandles(Integer maxResult, boolean recursive) { + return azureFileStorageClient.directorys().listHandlesWithRestResponseAsync(shareName, directoryPath, null, maxResult, null, snapshot, recursive, Context.NONE) + .flatMapMany(response -> nextPageForHandles(response, maxResult, recursive)); } + /** + * Closes a handle or handles opened on a directory or a file at the service. It is intended to be used alongside {@link DirectoryAsyncClient#getHandles(Integer, boolean)} . + * TODO: Will change the return type to how many handles have been closed. Implement one more API to force close all handles. + * TODO: @see Github Issue 4525 + * + *

Code 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 Flux forceCloseHandles(String handleId, boolean recursive) { - throw new UnsupportedOperationException(); + return azureFileStorageClient.directorys().forceCloseHandlesWithRestResponseAsync(shareName, directoryPath, handleId, null, null, snapshot, recursive, Context.NONE) + .flatMapMany(response -> nextPageForForceCloseHandles(response, handleId, recursive)); } - public Mono> createSubDirectory(String directoryName, Map metadata) { - throw new UnsupportedOperationException(); + /** + * Creates a subdirectory under current directory with specific name and returns a response of DirectoryAsyncClient to interact with it. + * + *

Code 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 Mono> createSubDirectory(String subDirectoryName) { + return createSubDirectory(subDirectoryName, null); } - public Mono deleteSubDirectory(String directoryName) { - throw new UnsupportedOperationException(); + /** + * Creates a subdirectory under current directory with specific name , metadata and returns a response of DirectoryAsyncClient to interact with it. + * + *

Code 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 Mono> createSubDirectory(String subDirectoryName, Map metadata) { + DirectoryAsyncClient createSubClient = getSubDirectoryClient(subDirectoryName); + return createSubClient.create(metadata) + .map(response -> new SimpleResponse<>(response, createSubClient)); } - public Mono> createFile(String fileName, long maxSize, FileHTTPHeaders httpHeaders, Map meatadata) { - throw new UnsupportedOperationException(); + /** + * Deletes the subdirectory with specific name in this directory. + * + *

Code 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 Mono deleteSubDirectory(String subDirectoryName) { + DirectoryAsyncClient deleteSubClient = getSubDirectoryClient(subDirectoryName); + return deleteSubClient.delete().map(VoidResponse::new); } + /** + * Creates a file in this directory with specific name, max number of results and returns a response of DirectoryInfo to interact with it. + * + *

Code 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 Mono> createFile(String fileName, long maxSize) { + return createFile(fileName, maxSize, null, null); + } + + /** + * Creates a file in this directory with specific name and returns a response of DirectoryInfo to interact with it. + * + *

Code 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 Mono> createFile(String fileName, long maxSize, FileHTTPHeaders httpHeaders, Map metadata) { + FileAsyncClient fileAsyncClient = getFileClient(fileName); + return fileAsyncClient.create(maxSize, httpHeaders, metadata).map(response -> new SimpleResponse<>(response, fileAsyncClient)); + } + + /** + * Deletes the file with specific name in this directory. + * + *

Code 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 Mono deleteFile(String fileName) { - throw new UnsupportedOperationException(); + FileAsyncClient fileAsyncClient = getFileClient(fileName); + return fileAsyncClient.delete().map(VoidResponse::new); + } + + /** + * Get snapshot id which attached to {@link DirectoryAsyncClient}. + * Return {@code null} if no snapshot id attached. + * + *

Code 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 Response createWithRestResponse(final DirectorysCreateResponse response) { + String eTag = response.deserializedHeaders().eTag(); + OffsetDateTime lastModified = response.deserializedHeaders().lastModified(); + DirectoryInfo directoryInfo = new DirectoryInfo(eTag, lastModified); + return new SimpleResponse<>(response, directoryInfo); + + } + + private Response getPropertiesResponse(DirectorysGetPropertiesResponse response) { + Map metadata = response.deserializedHeaders().metadata(); + String eTag = response.deserializedHeaders().eTag(); + OffsetDateTime offsetDateTime = response.deserializedHeaders().lastModified(); + boolean isServerEncrypted = response.deserializedHeaders().isServerEncrypted(); + + DirectoryProperties directoryProperties = new DirectoryProperties(metadata, eTag, offsetDateTime, isServerEncrypted); + return new SimpleResponse<>(response, directoryProperties); + } + + private Response setMetadataResponse(final DirectorysSetMetadataResponse response) { + String eTag = response.deserializedHeaders().eTag(); + boolean isServerEncrypted = response.deserializedHeaders().isServerEncrypted(); + + DirectorySetMetadataInfo directorySetMetadataInfo = new DirectorySetMetadataInfo(eTag, isServerEncrypted); + return new SimpleResponse<>(response, directorySetMetadataInfo); + } + + private Flux nextPageForFileAndDirecotries(final DirectorysListFilesAndDirectoriesSegmentResponse response, final String prefix, final Integer maxResult) { + List fileRefs = convertResponseAndGetNumOfResults(response); + + if (response.value().nextMarker() == null) { + return Flux.fromIterable(fileRefs); + } + Mono listResponse = azureFileStorageClient.directorys().listFilesAndDirectoriesSegmentWithRestResponseAsync(shareName, directoryPath, prefix, snapshot, response.value().nextMarker(), maxResult, null, Context.NONE); + Flux fileRefPublisher = listResponse.flatMapMany(newResponse -> nextPageForFileAndDirecotries(newResponse, prefix, maxResult)); + return Flux.fromIterable(fileRefs).concatWith(fileRefPublisher); + } + + private Flux nextPageForHandles(DirectorysListHandlesResponse response, Integer maxResult, boolean recursive) { + List handleItems = response.value().handleList(); + + if (response.value().nextMarker() == null) { + return Flux.fromIterable(handleItems); + } + Mono listResponse = azureFileStorageClient.directorys().listHandlesWithRestResponseAsync(shareName, directoryPath, response.value().nextMarker(), maxResult, null, snapshot, recursive, Context.NONE); + Flux fileRefPublisher = listResponse.flatMapMany(newResponse -> nextPageForHandles(newResponse, maxResult, recursive)); + return Flux.fromIterable(handleItems).concatWith(fileRefPublisher); + } + + private Flux nextPageForForceCloseHandles(DirectorysForceCloseHandlesResponse response, String handleId, boolean recursive) { + List handleCount = Arrays.asList(response.deserializedHeaders().numberOfHandlesClosed()); + + if (response.deserializedHeaders().marker() == null) { + return Flux.fromIterable(handleCount); + } + Mono listResponse = azureFileStorageClient.directorys().forceCloseHandlesWithRestResponseAsync(shareName, directoryPath, handleId, null, response.deserializedHeaders().marker(), snapshot, recursive, Context.NONE); + Flux fileRefPublisher = listResponse.flatMapMany(newResponse -> nextPageForForceCloseHandles(newResponse, handleId, recursive)); + return Flux.fromIterable(handleCount).concatWith(fileRefPublisher); + } + + private List convertResponseAndGetNumOfResults(DirectorysListFilesAndDirectoriesSegmentResponse response) { + List fileRefs = new ArrayList<>(); + response.value().segment().directoryItems().forEach(directoryItem -> fileRefs.add(new FileRef(directoryItem.name(), true, null))); + response.value().segment().fileItems().forEach(fileItem -> fileRefs.add(new FileRef(fileItem.name(), false, fileItem.properties()))); + return fileRefs; } } diff --git a/storage/client/file/src/main/java/com/azure/storage/file/DirectoryClient.java b/storage/client/file/src/main/java/com/azure/storage/file/DirectoryClient.java index 22d4063b0f410..44c84a0dade28 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/DirectoryClient.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/DirectoryClient.java @@ -4,78 +4,363 @@ package com.azure.storage.file; import com.azure.core.http.rest.Response; +import com.azure.core.http.rest.SimpleResponse; import com.azure.core.http.rest.VoidResponse; +import com.azure.storage.common.credentials.SASTokenCredential; +import com.azure.storage.common.credentials.SharedKeyCredential; import com.azure.storage.file.models.DirectoryInfo; import com.azure.storage.file.models.DirectoryProperties; +import com.azure.storage.file.models.DirectorySetMetadataInfo; import com.azure.storage.file.models.FileHTTPHeaders; import com.azure.storage.file.models.FileRef; import com.azure.storage.file.models.HandleItem; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - +import com.azure.storage.file.models.StorageErrorException; +import java.net.URL; import java.util.Map; +/** + * This class provides a client that contains all the operations for interacting with directory in Azure Storage File Service. + * Operations allowed by the client are creating, deleting and listing subdirectory and file, retrieving properties, , setting metadata + * and list or force close handles of the directory or file. + * + *

Instantiating 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 Response create() { + return create(null); + } - DirectoryClient() { - throw new UnsupportedOperationException(); + /** + * Creates a directory in the file share and returns a response of DirectoryInfo to interact with it. + * + *

Code 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 Response create(Map metadata) { + return directoryAsyncClient.create(metadata).block(); } - public static DirectoryClientBuilder syncBuilder() { - throw new UnsupportedOperationException(); + /** + * Deletes the directory in the file share. The directory must be empty before it can be deleted. + * + *

Code 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 Response getProperties() { + return directoryAsyncClient.getProperties().block(); } - public DirectoryClient getDirectoryClient(String directoryName) { - throw new UnsupportedOperationException(); + /** + * Sets the user-defined metadata to associate to the directory. + * + *

If {@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 Response setMetadata(Map metadata) { + return directoryAsyncClient.setMetadata(metadata).block(); } - public Mono> create(Map metadata) { - throw new UnsupportedOperationException(); + /** + * Lists all sub-directories and files in this directory without their prefix or maxResult. + * + *

Code 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 Iterable listFilesAndDirectories() { + return listFilesAndDirectories(null, null); } - public Mono delete() { - throw new UnsupportedOperationException(); + /** + * Lists all sub-directories and files in this directory with their prefix or snapshots. + * + *

Code 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 Iterable listFilesAndDirectories(String prefix, Integer maxResults) { + return directoryAsyncClient.listFilesAndDirectories(prefix, maxResults).toIterable(); } - public Mono> getProperties(String shareSnapshot) { - throw new UnsupportedOperationException(); + /** + * List of open handles on a directory or a file. + * + *

Code 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 Iterable getHandles(Integer maxResult, boolean recursive) { + return directoryAsyncClient.getHandles(maxResult, recursive).collectList().block(); } - public Mono> setMetadata(Map metadata) { - throw new UnsupportedOperationException(); + /** + * Closes a handle or handles opened on a directory or a file at the service. It is intended to be used alongside {@link DirectoryClient#getHandles(Integer, boolean)} . + * TODO: Will change the return type to how many handles have been closed. Implement one more API to force close all handles. + * TODO: @see Github Issue 4525 + * + *

Code 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 Iterable forceCloseHandles(String handleId, boolean recursive) { + return directoryAsyncClient.forceCloseHandles(handleId, recursive).collectList().block(); } - public Flux listFilesAndDirectories(String prefix, int maxResults, String shareSnapshot) { - throw new UnsupportedOperationException(); + /** + * Creates a subdirectory under current directory with specific name and returns a response of DirectoryClient to interact with it. + * + *

Code 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 Response createSubDirectory(String subDirectoryName) { + return createSubDirectory(subDirectoryName, null); } - public Flux getHandles(int maxResult, boolean recursive) { - throw new UnsupportedOperationException(); + /** + * Creates a subdirectory under current directory with specific name , metadata and returns a response of DirectoryClient to interact with it. + * + *

Code 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 Response createSubDirectory(String subDirectoryName, Map metadata) { + DirectoryClient directoryClient = getSubDirectoryClient(subDirectoryName); + return new SimpleResponse<>(directoryClient.create(metadata), directoryClient); } - public Flux forceCloseHandles(String handleId, boolean recursive) { - throw new UnsupportedOperationException(); + /** + * Deletes the subdirectory with specific name in this directory. The directory must be empty before it can be deleted. + * + *

Code 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 Mono> createSubDirectory(String directoryName, Map metadata) { - throw new UnsupportedOperationException(); + /** + * Creates a file in this directory with specific name, max number of results and returns a response of DirectoryInfo to interact with it. + * + *

Code 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 Response createFile(String fileName, long maxSize) { + return createFile(fileName, maxSize, null, null); } - public Mono deleteSubDirectory(String directoryName) { - throw new UnsupportedOperationException(); + /** + * Creates a file in this directory with specific name and returns a response of DirectoryInfo to interact with it. + * + *

Code 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 Response createFile(String fileName, long maxSize, FileHTTPHeaders httpHeaders, Map metadata) { + return directoryAsyncClient.createFile(fileName, maxSize, httpHeaders, metadata) + .map(response -> new SimpleResponse<>(response, new FileClient(response.value()))).block(); } - public Mono> createFile(String fileName, long maxSize, FileHTTPHeaders httpHeaders, Map meatadata) { - throw new UnsupportedOperationException(); + /** + * Deletes the file with specific name in this directory. + * + *

Code 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 Mono deleteFile(String fileName) { - throw new UnsupportedOperationException(); + /** + * Get snapshot id which attached to {@link DirectoryClient}. + * Return {@code null} if no snapshot id attached. + * + *

Code 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 policies; + private final RetryPolicy retryPolicy; + + private HttpLogDetailLevel logLevel; + private Configuration configuration; + private URL endpoint; + private String shareName; + private String directoryPath; + private SASTokenCredential sasTokenCredential; + private SharedKeyCredential sharedKeyCredential; + private HttpClient httpClient; + private HttpPipeline pipeline; + private String snapshot; + + /** + * Creates a builder instance that is able to configure and construct {@link DirectoryClient DirectoryClients} + * and {@link DirectoryAsyncClient DirectoryAsyncClients}. + */ + public DirectoryClientBuilder() { + retryPolicy = new RetryPolicy(); + logLevel = HttpLogDetailLevel.NONE; + policies = new ArrayList<>(); + + configuration = ConfigurationManager.getConfiguration(); + } + + /** + * Creates a {@link DirectoryAsyncClient} based on options set in the builder. Every time {@code buildAsyncClient()} is + * called a new instance of {@link DirectoryAsyncClient} is created. + * + *

+ * 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 policies = new ArrayList<>(); + + policies.add(new UserAgentPolicy(FileConfiguration.NAME, FileConfiguration.VERSION, configuration)); + policies.add(new RequestIdPolicy()); + policies.add(new AddDatePolicy()); + + if (sharedKeyCredential != null) { + policies.add(new SharedKeyCredentialPolicy(sharedKeyCredential)); + } else { + policies.add(new SASTokenCredentialPolicy(sasTokenCredential)); + } + + HttpPolicyProviders.addBeforeRetryPolicies(policies); + + policies.add(retryPolicy); + + policies.addAll(this.policies); + HttpPolicyProviders.addAfterRetryPolicies(policies); + policies.add(new HttpLoggingPolicy(logLevel)); + + HttpPipeline pipeline = HttpPipeline.builder() + .policies(policies.toArray(new HttpPipelinePolicy[0])) + .httpClient(httpClient) + .build(); + + return new DirectoryAsyncClient(endpoint, pipeline, shareName, directoryPath, snapshot); + } + + /** + * Creates a {@link DirectoryClient} based on options set in the builder. Every time {@code buildClient()} is + * called a new instance of {@link DirectoryClient} is created. + * + *

+ * 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) { + Map connectionStringPieces = new HashMap<>(); + for (String connectionStringPiece : connectionString.split(";")) { + String[] kvp = connectionStringPiece.split("=", 2); + connectionStringPieces.put(kvp[0].toLowerCase(Locale.ROOT), kvp[1]); + } + String accountName = connectionStringPieces.get(ACCOUNT_NAME); + try { + this.endpoint = new URL(String.format("https://%s.file.core.windows.net", accountName)); + } catch (MalformedURLException e) { + throw new IllegalArgumentException(String.format("There is no valid endpoint for the connection string. " + + "Connection String: %s", connectionString)); + } + } + + /** + * Sets the share that the constructed clients will interact with + * + * @param shareName Name of the share + * @return the updated DirectoryClientBuilder object + * @throws NullPointerException If {@code shareName} is {@code null}. + */ + public DirectoryClientBuilder shareName(String shareName) { + this.shareName = shareName; + return this; + } + + /** + * Sets the directory that the constructed clients will interact with + * + * @param directoryPath Path to the directory + * @return the updated DirectoryClientBuilder object + * @throws NullPointerException If {@code directoryPath} is {@code null}. + */ + public DirectoryClientBuilder directoryPath(String directoryPath) { + this.directoryPath = directoryPath; + return this; + } + + /** + * Sets the HTTP client to use for sending and receiving requests to and from the service. + * + * @param httpClient The HTTP client to use for requests. + * @return The updated DirectoryClientBuilder object. + * @throws NullPointerException If {@code httpClient} is {@code null}. + */ + public DirectoryClientBuilder httpClient(HttpClient httpClient) { + this.httpClient = httpClient; + return this; + } + + /** + * Adds a policy to the set of existing policies that are executed after the {@link RetryPolicy}. + * + * @param pipelinePolicy The retry policy for service requests. + * @return The updated DirectoryClientBuilder object. + * @throws NullPointerException If {@code pipelinePolicy} is {@code null}. + */ + public DirectoryClientBuilder addPolicy(HttpPipelinePolicy pipelinePolicy) { + this.policies.add(Objects.requireNonNull(pipelinePolicy)); + return this; + } + + /** + * Sets the logging level for HTTP requests and responses. + * + * @param logLevel The amount of logging output when sending and receiving HTTP requests/responses. + * @return The updated DirectoryClientBuilder object. + */ + public DirectoryClientBuilder httpLogDetailLevel(HttpLogDetailLevel logLevel) { + this.logLevel = logLevel; + return this; + } + + /** + * Sets the HTTP pipeline to use for the service client. + * + *

If {@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 Mono> create(long maxSize) { + return create(maxSize, null, null); + } + + /** + * Creates a file in the storage account and returns a response of FileInfo to interact with it. + * + *

Code 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 Mono> create(long maxSize, FileHTTPHeaders httpHeaders, Map metadata) { - throw new UnsupportedOperationException(); + return azureFileStorageClient.files().createWithRestResponseAsync(shareName, filePath, maxSize, null, metadata, httpHeaders, Context.NONE) + .map(this::createFileInfoResponse); } + /** + * Copies a blob or file to a destination file within the storage account. + * + *

Code 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 Mono> startCopy(String sourceUrl, Map metadata) { - throw new UnsupportedOperationException(); + return azureFileStorageClient.files().startCopyWithRestResponseAsync(shareName, filePath, sourceUrl, null, metadata, Context.NONE) + .map(this::startCopyResponse); } + /** + * Aborts a pending Copy File operation, and leaves a destination file with zero length and full metadata. + * + *

Code 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 Mono abortCopy(String copyId) { - throw new UnsupportedOperationException(); + return azureFileStorageClient.files().abortCopyWithRestResponseAsync(shareName, filePath, copyId, Context.NONE) + .map(VoidResponse::new); + } + + /** + * Downloads a file from the system, including its metadata and properties + * + *

Code 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 Mono downloadToFile(String downloadFilePath) { + return 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.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 Mono downloadToFile(String downloadFilePath, FileRange range) { + AsynchronousFileChannel channel = channelSetup(downloadFilePath); + return sliceFileRange(range) + .flatMap(chunk -> downloadWithProperties(chunk, false) + .map(dar -> dar.value().body()) + .subscribeOn(Schedulers.elastic()) + .flatMap(fbb -> FluxUtil.bytebufStreamToFile(fbb, channel, chunk.start() - (range == null ? 0 : range.start())) + .subscribeOn(Schedulers.elastic()) + .timeout(Duration.ofSeconds(DOWNLOAD_UPLOAD_CHUNK_TIMEOUT)) + .retry(3, throwable -> throwable instanceof IOException || throwable instanceof TimeoutException))) + .then() + .doOnTerminate(() -> channelCleanUp(channel)); + } + + private AsynchronousFileChannel channelSetup(String filePath) { + try { + return AsynchronousFileChannel.open(Paths.get(filePath), StandardOpenOption.READ, StandardOpenOption.WRITE); + } catch (IOException e) { + throw new UncheckedIOException(e); + } } - public Mono> downloadWithProperties(long offset, long length, boolean rangeGetContentMD5) { - throw new UnsupportedOperationException(); + private void channelCleanUp(AsynchronousFileChannel channel) { + try { + channel.close(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } } + private Flux sliceFileRange(FileRange fileRange) { + long offset = fileRange == null ? 0L : fileRange.start(); + Mono end; + if (fileRange != null) { + end = Mono.just(fileRange.end()); + } else { + end = Mono.empty(); + } + end = end.switchIfEmpty(getProperties().map(rb -> rb.value().contentLength())); + return end + .map(e -> { + List chunks = new ArrayList<>(); + for (long pos = offset; pos < e; pos += FILE_DEFAULT_BLOCK_SIZE) { + long count = FILE_DEFAULT_BLOCK_SIZE; + if (pos + count > e) { + count = e - pos; + } + chunks.add(new FileRange(pos, pos + count - 1)); + } + return chunks; + }) + .flatMapMany(Flux::fromIterable); + } + + /** + * 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.fileAsyncClient.downloadWithProperties} + * + * @return A response that only contains headers and response status code + */ + public Mono> downloadWithProperties() { + return downloadWithProperties(null, null); + } + + /** + * Downloads a file from the system, including its metadata and properties + * + *

Code 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 Mono> downloadWithProperties(FileRange range, Boolean rangeGetContentMD5) { + String rangeString = range == null ? null : range.toString(); + return azureFileStorageClient.files().downloadWithRestResponseAsync(shareName, filePath, null, rangeString, rangeGetContentMD5, Context.NONE) + .map(this::downloadWithPropertiesResponse); + } + + /** + * Deletes the file associate with the client. + * + *

Code 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 Mono delete() { - throw new UnsupportedOperationException(); + return azureFileStorageClient.files().deleteWithRestResponseAsync(shareName, filePath, Context.NONE) + .map(VoidResponse::new); } - public Mono> getProperties(String shareSnapshot) { - 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.fileAsyncClient.getProperties} + * + * @return Storage file properties + */ + public Mono> getProperties() { + return azureFileStorageClient.files().getPropertiesWithRestResponseAsync(shareName, filePath, snapshot, null, Context.NONE) + .map(this::getPropertiesResponse); } + /** + * Sets the user-defined httpHeaders to associate to the file. + * + *

If {@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 Mono> setHttpHeaders(long newFileSize, FileHTTPHeaders httpHeaders) { - throw new UnsupportedOperationException(); + return azureFileStorageClient.files().setHTTPHeadersWithRestResponseAsync(shareName, filePath, null, newFileSize, httpHeaders, Context.NONE) + .map(this::setHttpHeadersResponse); + } + + /** + * Sets the user-defined metadata to associate to the file. + * + *

If {@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 Mono> setMetadata(Map metadata) { + return azureFileStorageClient.files().setMetadataWithRestResponseAsync(shareName, filePath, null, metadata, Context.NONE) + .map(this::setMeatadataResponse); + } + + /** + * Uploads a range of bytes to the beginning of a file in storage file service. Upload operations performs an in-place write on the specified file. + * + *

Code 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 Mono> upload(Flux data, long length) { + FileRange range = new FileRange(0, length - 1); + return azureFileStorageClient.files().uploadRangeWithRestResponseAsync(shareName, filePath, range.toString(), FileRangeWriteType.UPDATE, length, data, null, null, Context.NONE) + .map(this::uploadResponse); + } + + /** + * Uploads a range of bytes to specific of a file in storage file service. Upload operations performs an in-place write on the specified file. + * + *

Code 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: + *
    + *
  • Update: Writes the bytes specified by the request body into the specified range.
  • + *
  • Clear: Clears the specified range and releases the space used in storage for that range. To clear a range, set the Content-Length header 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 Mono> upload(Flux data, long length, long offset, FileRangeWriteType type) { + FileRange range = new FileRange(offset, offset + length - 1); + return azureFileStorageClient.files().uploadRangeWithRestResponseAsync(shareName, filePath, range.toString(), type, length, data, null, null, Context.NONE) + .map(this::uploadResponse); + } + + /** + * Uploads file to storage file service. + * + *

      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 Mono uploadFromFile(String uploadFilePath) { + return uploadFromFile(uploadFilePath, FileRangeWriteType.UPDATE); } - public Mono> setMeatadata(Map meatadata) { - throw new UnsupportedOperationException(); + /** + * Uploads file to storage file service. + * + *

      Code 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: + *
        + *
      • Update: Writes the bytes specified by the request body into the specified range.
      • + *
      • Clear: Clears the specified range and releases the space used in storage for that range. To clear a range, set the Content-Length header to zero.
      • + *
          + * + * @return An empty response. + * @throws UncheckedIOException If an I/O error occurs. + */ + public Mono uploadFromFile(String uploadFilePath, FileRangeWriteType type) { + AsynchronousFileChannel channel = channelSetup(uploadFilePath); + return Flux.fromIterable(sliceFile(uploadFilePath)) + .flatMap(chunk -> { + return upload(FluxUtil.byteBufStreamFromFile(channel, chunk.start(), chunk.end() - chunk.start() + 1), chunk.end() - chunk.start() + 1, chunk.start(), type) + .timeout(Duration.ofSeconds(DOWNLOAD_UPLOAD_CHUNK_TIMEOUT)) + .retry(3, throwable -> throwable instanceof IOException || throwable instanceof TimeoutException); + }) + .then() + .doOnTerminate(() -> channelCleanUp(channel)); } - public Mono> upload(FileRangeWriteType type, long offset, long length, Flux data) { - throw new UnsupportedOperationException(); + private List sliceFile(String path) { + File file = new File(path); + assert file.exists(); + List ranges = new ArrayList<>(); + for (long pos = 0; pos < file.length(); pos += FILE_DEFAULT_BLOCK_SIZE) { + long count = FILE_DEFAULT_BLOCK_SIZE; + if (pos + count > file.length()) { + count = file.length() - pos; + } + ranges.add(new FileRange(pos, pos + count - 1)); + } + return ranges; } - public Flux listRanges(long offset, long length, String shareSnapshot) { - throw new UnsupportedOperationException(); + /** + * List of valid ranges for a file. + * + *

          Code Samples

          + * + *

          List all ranges for the file client.

          + * + * {@codesnippet com.azure.storage.file.fileAsyncClient.listRanges} + * + * @return {@link FileRange ranges} in the files. + */ + public Flux listRanges() { + return azureFileStorageClient.files().getRangeListWithRestResponseAsync(shareName, filePath, snapshot, null, null, Context.NONE) + .flatMapMany(this::convertListRangesResponseToFileRangeInfo); } - public Flux listHandles(int maxResults) { - throw new UnsupportedOperationException(); + /** + * List of valid ranges for a file. + * + *

          Code 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 Flux listRanges(FileRange range) { + String rangeString = range == null ? null : range.toString(); + return azureFileStorageClient.files().getRangeListWithRestResponseAsync(shareName, filePath, snapshot, null, rangeString, Context.NONE) + .flatMapMany(this::convertListRangesResponseToFileRangeInfo); } + /** + * List of open handles on a file. + * + *

          Code 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 Flux listHandles() { + return listHandles(null); + } + + /** + * List of open handles on a file. + * + *

          Code 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 Flux listHandles(Integer maxResults) { + return azureFileStorageClient.files().listHandlesWithRestResponseAsync(shareName, filePath, null, maxResults, null, snapshot, Context.NONE) + .flatMapMany(response -> nextPageForHandles(response, maxResults)); + } + + /** + * Closes a handle or handles opened on a file at the service. It is intended to be used alongside {@link FileAsyncClient#listHandles()} (Integer)} . + * TODO: Will change the return type to how many handles have been closed. Implement one more API to force close all handles. + * TODO: @see Github Issue 4525 + * + *

          Code 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 Flux forceCloseHandles(String handleId) { - throw new UnsupportedOperationException(); + return azureFileStorageClient.files().forceCloseHandlesWithRestResponseAsync(shareName, filePath, handleId, null, null, snapshot, Context.NONE) + .flatMapMany(response -> nextPageForForceCloseHandles(response, handleId)); + } + + /** + * Get snapshot id which attached to {@link FileAsyncClient}. + * Return {@code null} if no snapshot id attached. + * + *

          Code 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 Flux nextPageForForceCloseHandles(final FilesForceCloseHandlesResponse response, final String handleId) { + List handleCount = Arrays.asList(response.deserializedHeaders().numberOfHandlesClosed()); + + if (response.deserializedHeaders().marker() == null) { + return Flux.fromIterable(handleCount); + } + Mono listResponse = azureFileStorageClient.files().forceCloseHandlesWithRestResponseAsync(shareName, filePath, handleId, null, response.deserializedHeaders().marker(), snapshot, Context.NONE); + Flux fileRefPublisher = listResponse.flatMapMany(newResponse -> nextPageForForceCloseHandles(newResponse, handleId)); + return Flux.fromIterable(handleCount).concatWith(fileRefPublisher); + } + + private Flux nextPageForHandles(final FilesListHandlesResponse response, final Integer maxResults) { + List handleItems = response.value().handleList(); + + if (response.value().nextMarker() == null) { + return Flux.fromIterable(handleItems); + } + + Mono listResponse = azureFileStorageClient.files().listHandlesWithRestResponseAsync(shareName, filePath, response.value().nextMarker(), maxResults, null, snapshot, Context.NONE); + Flux fileRefPublisher = listResponse.flatMapMany(newResponse -> nextPageForHandles(newResponse, maxResults)); + return Flux.fromIterable(handleItems).concatWith(fileRefPublisher); + } + + private Response createFileInfoResponse(final FilesCreateResponse response) { + String eTag = response.deserializedHeaders().eTag(); + OffsetDateTime lastModified = response.deserializedHeaders().lastModified(); + boolean isServerEncrypted = response.deserializedHeaders().isServerEncrypted(); + FileInfo fileInfo = new FileInfo(eTag, lastModified, isServerEncrypted); + return new SimpleResponse<>(response, fileInfo); + } + + private Response startCopyResponse(final FilesStartCopyResponse response) { + String eTag = response.deserializedHeaders().eTag(); + OffsetDateTime lastModified = response.deserializedHeaders().lastModified(); + String copyId = response.deserializedHeaders().copyId(); + CopyStatusType copyStatus = response.deserializedHeaders().copyStatus(); + FileCopyInfo fileCopyInfo = new FileCopyInfo(eTag, lastModified, copyId, copyStatus); + return new SimpleResponse<>(response, fileCopyInfo); + } + + private Response setHttpHeadersResponse(final FilesSetHTTPHeadersResponse response) { + String eTag = response.deserializedHeaders().eTag(); + OffsetDateTime lastModified = response.deserializedHeaders().lastModified(); + boolean isServerEncrypted = response.deserializedHeaders().isServerEncrypted(); + FileInfo fileInfo = new FileInfo(eTag, lastModified, isServerEncrypted); + return new SimpleResponse<>(response, fileInfo); + } + private Response downloadWithPropertiesResponse(final FilesDownloadResponse response) { + String eTag = response.deserializedHeaders().eTag(); + OffsetDateTime lastModified = response.deserializedHeaders().lastModified(); + Map metadata = response.deserializedHeaders().metadata(); + Long contentLength = response.deserializedHeaders().contentLength(); + String contentType = response.deserializedHeaders().contentType(); + String contentRange = response.deserializedHeaders().contentRange(); + Flux body = response.value(); + FileDownloadInfo fileDownloadInfo = new FileDownloadInfo(eTag, lastModified, metadata, contentLength, contentType, contentRange, body); + return new SimpleResponse<>(response, fileDownloadInfo); + } + + private Response getPropertiesResponse(final FilesGetPropertiesResponse response) { + FileGetPropertiesHeaders headers = response.deserializedHeaders(); + String eTag = headers.eTag(); + OffsetDateTime lastModified = headers.lastModified(); + Map metadata = headers.metadata(); + String fileType = headers.fileType(); + Long contentLength = headers.contentLength(); + String contentType = headers.contentType(); + byte[] contentMD5; + try { + contentMD5 = headers.contentMD5(); + } catch (NullPointerException e) { + contentMD5 = null; + } + String contentEncoding = headers.contentEncoding(); + String cacheControl = headers.cacheControl(); + String contentDisposition = headers.contentDisposition(); + OffsetDateTime copyCompletionTime = headers.copyCompletionTime(); + String copyStatusDescription = headers.copyStatusDescription(); + String copyId = headers.copyId(); + String copyProgress = headers.copyProgress(); + String copySource = headers.copySource(); + CopyStatusType copyStatus = headers.copyStatus(); + Boolean isServerEncrpted = headers.isServerEncrypted(); + FileProperties fileProperties = new FileProperties(eTag, lastModified, metadata, fileType, contentLength, + contentType, contentMD5, contentEncoding, cacheControl, contentDisposition, copyCompletionTime, copyStatusDescription, + copyId, copyProgress, copySource, copyStatus, isServerEncrpted); + return new SimpleResponse<>(response, fileProperties); + } + + private Response uploadResponse(final FilesUploadRangeResponse response) { + FileUploadRangeHeaders headers = response.deserializedHeaders(); + String eTag = headers.eTag(); + OffsetDateTime lastModified = headers.lastModified(); + byte[] contentMD5; + try { + contentMD5 = headers.contentMD5(); + } catch (NullPointerException e) { + contentMD5 = null; + } + Boolean isServerEncrypted = headers.isServerEncrypted(); + FileUploadInfo fileUploadInfo = new FileUploadInfo(eTag, lastModified, contentMD5, isServerEncrypted); + return new SimpleResponse<>(response, fileUploadInfo); + } + + private Response setMeatadataResponse(final FilesSetMetadataResponse response) { + String eTag = response.deserializedHeaders().eTag(); + boolean isServerEncrypted = response.deserializedHeaders().isServerEncrypted(); + FileMetadataInfo fileMetadataInfo = new FileMetadataInfo(eTag, isServerEncrypted); + return new SimpleResponse<>(response, fileMetadataInfo); + } + + private Flux convertListRangesResponseToFileRangeInfo(FilesGetRangeListResponse response) { + List fileRanges = new ArrayList<>(); + response.value().forEach(range -> { + long start = range.start(); + long end = range.end(); + fileRanges.add(new FileRange(start, end)); + }); + return Flux.fromIterable(fileRanges); } } diff --git a/storage/client/file/src/main/java/com/azure/storage/file/FileClient.java b/storage/client/file/src/main/java/com/azure/storage/file/FileClient.java index 3d6bacb4ff3ea..4736673bee43e 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/FileClient.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/FileClient.java @@ -5,78 +5,444 @@ import com.azure.core.http.rest.Response; import com.azure.core.http.rest.VoidResponse; +import com.azure.storage.common.credentials.SASTokenCredential; +import com.azure.storage.common.credentials.SharedKeyCredential; import com.azure.storage.file.models.FileCopyInfo; import com.azure.storage.file.models.FileDownloadInfo; 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.HandleItem; +import com.azure.storage.file.models.StorageErrorException; import io.netty.buffer.ByteBuf; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - +import java.net.URL; import java.util.Map; +import reactor.core.publisher.Flux; +/** + * This class provides a client that contains all the operations for interacting files under Azure Storage File Service. + * Operations allowed by the client are creating, uploading, copying, listing, downloading, and deleting files. + * + *

          Instantiating 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 Response create(long maxSize) { + return fileAsyncClient.create(maxSize).block(); + } + + /** + * Creates a file in the storage account and returns a response of 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#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 Response create(long maxSize, FileHTTPHeaders httpHeaders, Map metadata) { + return fileAsyncClient.create(maxSize, httpHeaders, metadata).block(); + } + + /** + * Copies a blob or file to a destination file within the storage account. + * + *

          Code 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 Response startCopy(String sourceUrl, Map metadata) { + return fileAsyncClient.startCopy(sourceUrl, metadata).block(); + } + + /** + * Aborts a pending Copy File operation, and leaves a destination file with zero length and full metadata. + * + *

          Code 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 Response downloadWithProperties() { + return fileAsyncClient.downloadWithProperties(null, null).block(); + } + + /** + * Downloads a file from the system, including its metadata and properties + * + *

          Code 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 Response downloadWithProperties(FileRange range, Boolean rangeGetContentMD5) { + return fileAsyncClient.downloadWithProperties(range, rangeGetContentMD5).block(); + } - FileClient() { - throw new UnsupportedOperationException(); + /** + * Deletes the file associate with the client. + * + *

          Code 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 Response getProperties() { + return fileAsyncClient.getProperties().block(); } - public Mono> create(long maxSize, FileHTTPHeaders httpHeaders, Map metadata) { - throw new UnsupportedOperationException(); + /** + * Sets the user-defined httpHeaders to associate to the file. + * + *

          If {@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 Response setHttpHeaders(long newFileSize, FileHTTPHeaders httpHeaders) { + return fileAsyncClient.setHttpHeaders(newFileSize, httpHeaders).block(); } - public Mono> startCopy(String sourceUrl, Map metadata) { - throw new UnsupportedOperationException(); + /** + * Sets the user-defined metadata to associate to the file. + * + *

          If {@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 Response setMetadata(Map metadata) { + return fileAsyncClient.setMetadata(metadata).block(); } - public Mono abortCopy(String copyId) { - throw new UnsupportedOperationException(); + /** + * Uploads a range of bytes to the beginning of a file in storage file service. Upload operations performs an in-place write on the specified file. + * + *

          Code 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 Response upload(ByteBuf data, long length) { + return fileAsyncClient.upload(Flux.just(data), length).block(); } - public Mono> downloadWithProperties(long offset, long length, boolean rangeGetContentMD5) { - throw new UnsupportedOperationException(); + /** + * Uploads a range of bytes to specific of a file in storage file service. Upload operations performs an in-place write on the specified file. + * + *

          Code 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: + *
            + *
          • Update: Writes the bytes specified by the request body into the specified range.
          • + *
          • Clear: Clears the specified range and releases the space used in storage for that range. To clear a range, set the Content-Length header 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 Response upload(ByteBuf data, long length, int offset, FileRangeWriteType type) { + return fileAsyncClient.upload(Flux.just(data), length, offset, type).block(); } - public Mono delete() { - throw new UnsupportedOperationException(); + /** + * Uploads file to storage file service. + * + *

              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 Mono> getProperties(String shareSnapshot) { - throw new UnsupportedOperationException(); + /** + * Uploads file to storage file service. + * + *

              Code 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: + *
                + *
              • Update: Writes the bytes specified by the request body into the specified range.
              • + *
              • Clear: Clears the specified range and releases the space used in storage for that range. To clear a range, set the Content-Length header to zero.
              • + *
                  + */ + public void uploadFromFile(String uploadFilePath, FileRangeWriteType type) { + fileAsyncClient.uploadFromFile(uploadFilePath, type).block(); } - public Mono> setHttpHeaders(long newFileSize, FileHTTPHeaders httpHeaders) { - throw new UnsupportedOperationException(); + /** + * List of valid ranges for a file. + * + *

                  Code Samples

                  + * + *

                  List all ranges for the file client.

                  + * + * {@codesnippet com.azure.storage.file.fileClient.listRanges} + * + * @return {@link FileRange ranges} in the files. + */ + public Iterable listRanges() { + return fileAsyncClient.listRanges(null).toIterable(); } - public Mono> setMeatadata(Map meatadata) { - throw new UnsupportedOperationException(); + /** + * List of valid ranges for a file. + * + *

                  Code 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 Iterable listRanges(FileRange range) { + return fileAsyncClient.listRanges(range).toIterable(); } - public Mono> upload(FileRangeWriteType type, long offset, long length, Flux data) { - throw new UnsupportedOperationException(); + /** + * List of open handles on a file. + * + *

                  Code 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 Iterable listHandles() { + return listHandles(null); } - public Flux listRanges(long offset, long length, String shareSnapshot) { - throw new UnsupportedOperationException(); + /** + * List of open handles on a file. + * + *

                  Code 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 Iterable listHandles(Integer maxResults) { + return fileAsyncClient.listHandles(maxResults).toIterable(); } - public Flux listHandles(int maxResults) { - throw new UnsupportedOperationException(); + /** + * Closes a handle or handles opened on a file at the service. It is intended to be used alongside {@link FileClient#listHandles()} (Integer)} . + * TODO: Will change the return type to how many handles have been closed. Implement one more API to force close all handles. + * TODO: @see Github Issue 4525 + * + *

                  Code 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 Iterable forceCloseHandles(String handleId) { + return fileAsyncClient.forceCloseHandles(handleId).toIterable(); } - public Flux forceCloseHandles(String handleId) { - throw new UnsupportedOperationException(); + /** + * Get snapshot id which attached to {@link FileClient}. + * Return {@code null} if no snapshot id attached. + * + *

                  Code 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 policies; + private final RetryPolicy retryPolicy; + + private HttpLogDetailLevel logLevel; + private Configuration configuration; + private URL endpoint; + private String shareName; + private String filePath; + private SASTokenCredential sasTokenCredential; + private SharedKeyCredential sharedKeyCredential; + private HttpClient httpClient; + private HttpPipeline pipeline; + private String snapshot; + + /** + * Creates a builder instance that is able to configure and construct {@link FileClient FileClients} + * and {@link FileAsyncClient FileAsyncClients}. + */ + public FileClientBuilder() { + retryPolicy = new RetryPolicy(); + logLevel = HttpLogDetailLevel.NONE; + policies = new ArrayList<>(); + + configuration = ConfigurationManager.getConfiguration(); + } + + /** + * Creates a {@link FileAsyncClient} based on options set in the builder. Every time {@code buildAsyncClient()} is + * called a new instance of {@link FileAsyncClient} is created. + * + *

                  + * 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 policies = new ArrayList<>(); + + policies.add(new UserAgentPolicy(FileConfiguration.NAME, FileConfiguration.VERSION, configuration)); + policies.add(new RequestIdPolicy()); + policies.add(new AddDatePolicy()); + + if (sharedKeyCredential != null) { + policies.add(new SharedKeyCredentialPolicy(sharedKeyCredential)); + } else { + policies.add(new SASTokenCredentialPolicy(sasTokenCredential)); + } + + HttpPolicyProviders.addBeforeRetryPolicies(policies); + + policies.add(retryPolicy); + + policies.addAll(this.policies); + HttpPolicyProviders.addAfterRetryPolicies(policies); + policies.add(new HttpLoggingPolicy(logLevel)); + + HttpPipeline pipeline = HttpPipeline.builder() + .policies(policies.toArray(new HttpPipelinePolicy[0])) + .httpClient(httpClient) + .build(); + + return new FileAsyncClient(endpoint, pipeline, shareName, filePath, snapshot); + } + + /** + * Creates a {@link FileClient} based on options set in the builder. Every time {@code buildClient()} is + * called a new instance of {@link FileClient} is created. + * + *

                  + * 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) { + Map connectionStringPieces = new HashMap<>(); + for (String connectionStringPiece : connectionString.split(";")) { + String[] kvp = connectionStringPiece.split("=", 2); + connectionStringPieces.put(kvp[0].toLowerCase(Locale.ROOT), kvp[1]); + } + String accountName = connectionStringPieces.get(ACCOUNT_NAME); + try { + this.endpoint = new URL(String.format("https://%s.file.core.windows.net", accountName)); + } catch (MalformedURLException e) { + throw new IllegalArgumentException(String.format("There is no valid endpoint for the connection string. " + + "Connection String: %s", connectionString)); + } + } + + /** + * Sets the share that the constructed clients will interact with + * + * @param shareName Name of the share + * @return the updated FileClientBuilder object + * @throws NullPointerException If {@code shareName} is {@code null}. + */ + public FileClientBuilder shareName(String shareName) { + this.shareName = shareName; + return this; + } + + /** + * Sets the file that the constructed clients will interact with + * + * @param filePath Path of the file, mush end up with the file name. + * @return the updated FileClientBuilder object + * @throws NullPointerException If {@code filePath} is {@code null}. + */ + public FileClientBuilder filePath(String filePath) { + this.filePath = filePath; + return this; + } + + /** + * Sets the HTTP client to use for sending and receiving requests to and from the service. + * + * @param httpClient The HTTP client to use for requests. + * @return The updated FileClientBuilder object. + * @throws NullPointerException If {@code httpClient} is {@code null}. + */ + public FileClientBuilder httpClient(HttpClient httpClient) { + this.httpClient = httpClient; + return this; + } + + /** + * Adds a policy to the set of existing policies that are executed after the {@link RetryPolicy}. + * + * @param pipelinePolicy The retry policy for service requests. + * @return The updated FileClientBuilder object. + * @throws NullPointerException If {@code pipelinePolicy} is {@code null}. + */ + public FileClientBuilder addPolicy(HttpPipelinePolicy pipelinePolicy) { + this.policies.add(pipelinePolicy); + return this; + } + + /** + * Sets the logging level for HTTP requests and responses. + * + * @param logLevel The amount of logging output when sending and receiving HTTP requests/responses. + * @return The updated FileClientBuilder object. + */ + public FileClientBuilder httpLogDetailLevel(HttpLogDetailLevel logLevel) { + this.logLevel = logLevel; + return this; + } + + /** + * Sets the HTTP pipeline to use for the service client. + * + *

                  If {@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 Flux listShares() { + return listShares(null); } + /** + * Lists the shares in the Storage account that pass the options filter. + * + *

                  Set 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 Flux listShares(ListSharesOptions options) { - throw new UnsupportedOperationException(); + return listShares(null, options); } + /** + * Lists the shares in the storage account that pass the filter starting at the specified marker. + * + * @param marker Starting point to list the shares + * @param options Options for listing shares + * @return {@link ShareItem Shares} in the storage account that satisfy the filter requirements + */ + private Flux listShares(String marker, ListSharesOptions options) { + String prefix = null; + Integer maxResults = null; + List include = new ArrayList<>(); + + if (options != null) { + prefix = options.prefix(); + maxResults = options.maxResults(); + + if (options.includeMetadata()) { + include.add(ListSharesIncludeType.fromString(ListSharesIncludeType.METADATA.toString())); + } + + if (options.includeSnapshots()) { + include.add(ListSharesIncludeType.fromString(ListSharesIncludeType.SNAPSHOTS.toString())); + } + } + + return azureFileStorageClient.services().listSharesSegmentWithRestResponseAsync(prefix, marker, maxResults, include, null, Context.NONE) + .flatMapMany(response -> Flux.fromIterable(response.value().shareItems())); + } + + /* + * Helper function used to auto-enumerate through paged responses + */ + private Flux listShares(ServicesListSharesSegmentResponse response, List include, Context context) { + ListSharesResponse value = response.value(); + Mono result = azureFileStorageClient.services() + .listSharesSegmentWithRestResponseAsync(value.prefix(), value.marker(), value.maxResults(), include, null, context); + + return result.flatMapMany(r -> extractAndFetchShares(r, include, context)); + } + + /* + * Helper function used to auto-enumerate through paged responses + */ + private Publisher extractAndFetchShares(ServicesListSharesSegmentResponse response, List include, Context context) { + String nextPageLink = response.value().nextMarker(); + if (ImplUtils.isNullOrEmpty(nextPageLink)) { + return Flux.fromIterable(response.value().shareItems()); + } + + return Flux.fromIterable(response.value().shareItems()).concatWith(listShares(response, include, context)); + } + + /** + * Retrieves the properties of the storage account's File service. The properties range from storage analytics and + * metrics to CORS (Cross-Origin Resource Sharing). + * + *

                  Code Samples

                  + * + *

                  Retrieve File service properties

                  + * + * {@codesnippet com.azure.storage.file.fileServiceAsyncClient.getProperties} + * + * @return Storage account File service properties + */ public Mono> getProperties() { - throw new UnsupportedOperationException(); + return azureFileStorageClient.services().getPropertiesWithRestResponseAsync(Context.NONE) + .map(response -> new SimpleResponse<>(response, response.value())); + } + + /** + * Sets the properties for the storage account's File service. The properties range from storage analytics and + * metric to CORS (Cross-Origin Resource Sharing). + * + * To maintain the CORS in the Queue service pass a {@code null} value for {@link FileServiceProperties#cors() CORS}. + * To disable all CORS in the Queue service pass an empty list for {@link FileServiceProperties#cors() CORS}. + * + *

                  Code 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 + *
                    + *
                  • A CORS rule is missing one of its fields
                  • + *
                  • More than five CORS rules will exist for the Queue service
                  • + *
                  • Size of all CORS rules exceeds 2KB
                  • + *
                  • + * Length of {@link CorsRule#allowedHeaders() allowed headers}, {@link CorsRule#exposedHeaders() exposed headers}, + * or {@link CorsRule#allowedOrigins() allowed origins} exceeds 256 characters. + *
                  • + *
                  • {@link CorsRule#allowedMethods() Allowed methods} isn't DELETE, GET, HEAD, MERGE, POST, OPTIONS, or PUT
                  • + *
                  + */ + public Mono setProperties(FileServiceProperties properties) { + return azureFileStorageClient.services().setPropertiesWithRestResponseAsync(properties, Context.NONE) + .map(VoidResponse::new); } - public Mono setProperties() { - throw new UnsupportedOperationException(); + /** + * Creates a share in the storage account with the specified name and returns a ShareAsyncClient to interact with it. + * + *

                  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 Mono> createShare(String shareName) { + return createShare(shareName, null, null); } - public Mono> createShare(String shareName, Map metadata, int quotaInGB) { - throw new UnsupportedOperationException(); + /** + * Creates a share in the storage account with the specified name, metadata, and quota and returns a ShareAsyncClient to + * interact with it. + * + *

                  Code 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 Mono> createShare(String shareName, Map metadata, Integer quotaInGB) { + ShareAsyncClient shareAsyncClient = new ShareAsyncClient(azureFileStorageClient, shareName); + + return shareAsyncClient.create(metadata, quotaInGB) + .map(response -> new SimpleResponse<>(response, shareAsyncClient)); } - public Mono deleteShare(String shareName, String shareSnapshot) { - throw new UnsupportedOperationException(); + /** + * Deletes the share in the storage account with the given name. + * + *

                  Code 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 Mono deleteShare(String shareName) { + return deleteShare(shareName, null); } + + /** + * Deletes the specific snapshot of the share in the storage account with the given name. Snapshot are identified + * by the time they were created. + * + *

                  Code 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 Mono deleteShare(String shareName, String snapshot) { + DeleteSnapshotsOptionType deleteSnapshots = null; + if (ImplUtils.isNullOrEmpty(snapshot)) { + deleteSnapshots = DeleteSnapshotsOptionType.fromString(DeleteSnapshotsOptionType.INCLUDE.toString()); + } + return azureFileStorageClient.shares().deleteWithRestResponseAsync(shareName, snapshot, null, deleteSnapshots, Context.NONE) + .map(VoidResponse::new); + } + } diff --git a/storage/client/file/src/main/java/com/azure/storage/file/FileServiceClient.java b/storage/client/file/src/main/java/com/azure/storage/file/FileServiceClient.java index fd808bf1d6fde..2dd4656926e15 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/FileServiceClient.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/FileServiceClient.java @@ -1,52 +1,242 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + package com.azure.storage.file; import com.azure.core.http.rest.Response; +import com.azure.core.http.rest.SimpleResponse; import com.azure.core.http.rest.VoidResponse; +import com.azure.storage.common.credentials.SASTokenCredential; +import com.azure.storage.common.credentials.SharedKeyCredential; +import com.azure.storage.file.models.CorsRule; import com.azure.storage.file.models.FileServiceProperties; import com.azure.storage.file.models.ListSharesOptions; import com.azure.storage.file.models.ShareItem; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - +import com.azure.storage.file.models.StorageErrorException; +import java.net.URL; import java.util.Map; -public class FileServiceClient { +/** + * This class provides a fileServiceAsyncClient that contains all the operations for interacting with a file account in Azure Storage. + * Operations allowed by the fileServiceAsyncClient are creating, listing, and deleting shares and retrieving and updating properties + * of the account. + * + *

                  Instantiating 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 Iterable listShares() { + return listShares(null); } - public ShareClient getShareClient(String shareName) { - throw new UnsupportedOperationException(); + /** + * Lists the shares in the Storage account that pass the options filter. + * + *

                  Set 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 Iterable listShares(ListSharesOptions options) { + return fileServiceAsyncClient.listShares(options).toIterable(); + } + + /** + * Retrieves the properties of the storage account's File service. The properties range from storage analytics and + * metrics to CORS (Cross-Origin Resource Sharing). + * + *

                  Code Samples

                  + * + *

                  Retrieve File service properties

                  + * + * {@codesnippet com.azure.storage.file.fileServiceClient.getProperties} + * + * @return Storage account File service properties + */ + public Response getProperties() { + return fileServiceAsyncClient.getProperties().block(); } - public Flux listShares(ListSharesOptions options) { - throw new UnsupportedOperationException(); + /** + * Sets the properties for the storage account's File service. The properties range from storage analytics and + * metric to CORS (Cross-Origin Resource Sharing). + * + * To maintain the CORS in the Queue service pass a {@code null} value for {@link FileServiceProperties#cors() CORS}. + * To disable all CORS in the Queue service pass an empty list for {@link FileServiceProperties#cors() CORS}. + * + *

                  Code 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 + *
                    + *
                  • A CORS rule is missing one of its fields
                  • + *
                  • More than five CORS rules will exist for the Queue service
                  • + *
                  • Size of all CORS rules exceeds 2KB
                  • + *
                  • + * Length of {@link CorsRule#allowedHeaders() allowed headers}, {@link CorsRule#exposedHeaders() exposed headers}, + * or {@link CorsRule#allowedOrigins() allowed origins} exceeds 256 characters. + *
                  • + *
                  • {@link CorsRule#allowedMethods() Allowed methods} isn't DELETE, GET, HEAD, MERGE, POST, OPTIONS, or PUT
                  • + *
                  + */ + public VoidResponse setProperties(FileServiceProperties properties) { + return fileServiceAsyncClient.setProperties(properties).block(); } - public Mono> getProperties() { - throw new UnsupportedOperationException(); + /** + * Creates a share in the storage account with the specified name and returns a ShareClient to interact with it. + * + *

                  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 Response createShare(String shareName) { + return createShare(shareName, null, null); } - public Mono setProperties() { - throw new UnsupportedOperationException(); + /** + * Creates a share in the storage account with the specified name and metadata and returns a ShareClient to + * interact with it. + * + *

                  Code 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 Response createShare(String shareName, Map metadata, Integer quotaInGB) { + ShareClient shareClient = getShareClient(shareName); + return new SimpleResponse<>(shareClient.create(metadata, quotaInGB), shareClient); } - public Mono> createShare(String shareName, Map metadata, int quotaInGB) { - throw new UnsupportedOperationException(); + /** + * Deletes the share in the storage account with the given name + * + *

                  Code 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 Mono deleteShare(String shareName, String shareSnapshot) { - throw new UnsupportedOperationException(); + /** + * Deletes the specific snapshot of the share in the storage account with the given name. Snapshot are identified + * by the time they were created. + * + *

                  Code 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 policies; + + private URL endpoint; + private SASTokenCredential sasTokenCredential; + private SharedKeyCredential sharedKeyCredential; + private HttpClient httpClient; + private HttpPipeline pipeline; + private HttpLogDetailLevel logLevel; + private RetryPolicy retryPolicy; + private Configuration configuration; + + /** + * Creates a builder instance that is able to configure and construct {@link FileServiceClient FileServiceClients} + * and {@link FileServiceAsyncClient FileServiceAsyncClients}. + */ + public FileServiceClientBuilder() { + retryPolicy = new RetryPolicy(); + logLevel = HttpLogDetailLevel.NONE; + policies = new ArrayList<>(); + configuration = ConfigurationManager.getConfiguration(); + } + + /** + * Creates a {@link FileServiceAsyncClient} based on options set in the builder. Every time {@code buildAsyncClient()} is + * called a new instance of {@link FileServiceAsyncClient} is created. + * + *

                  + * 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 policies = new ArrayList<>(); + + policies.add(new UserAgentPolicy(FileConfiguration.NAME, FileConfiguration.VERSION, configuration)); + policies.add(new RequestIdPolicy()); + policies.add(new AddDatePolicy()); + + if (sharedKeyCredential != null) { + policies.add(new SharedKeyCredentialPolicy(sharedKeyCredential)); + } else { + policies.add(new SASTokenCredentialPolicy(sasTokenCredential)); + } + + HttpPolicyProviders.addBeforeRetryPolicies(policies); + + policies.add(retryPolicy); + + policies.addAll(this.policies); + HttpPolicyProviders.addAfterRetryPolicies(policies); + policies.add(new HttpLoggingPolicy(logLevel)); + + HttpPipeline pipeline = HttpPipeline.builder() + .policies(policies.toArray(new HttpPipelinePolicy[0])) + .httpClient(httpClient) + .build(); + + return new FileServiceAsyncClient(endpoint, pipeline); + } + + /** + * Creates a {@link FileServiceClient} based on options set in the builder. Every time {@code buildClient()} is + * called a new instance of {@link FileServiceClient} is created. + * + *

                  + * 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) { + Map connectionStringPieces = new HashMap<>(); + for (String connectionStringPiece : connectionString.split(";")) { + String[] kvp = connectionStringPiece.split("=", 2); + connectionStringPieces.put(kvp[0].toLowerCase(Locale.ROOT), kvp[1]); + } + String accountName = connectionStringPieces.get(ACCOUNT_NAME); + try { + this.endpoint = new URL(String.format("https://%s.file.core.windows.net", accountName)); + } catch (MalformedURLException e) { + throw new IllegalArgumentException(String.format("There is no valid endpoint for the connection string. " + + "Connection String: %s", connectionString)); + } + } + + /** + * Sets the HTTP client to use for sending and receiving requests to and from the service. + * + * @param httpClient The HTTP client to use for requests. + * @return The updated FileServiceClientBuilder object. + * @throws NullPointerException If {@code httpClient} is {@code null}. + */ + public FileServiceClientBuilder httpClient(HttpClient httpClient) { + this.httpClient = Objects.requireNonNull(httpClient); + return this; + } + + /** + * Adds a policy to the set of existing policies that are executed after the {@link RetryPolicy}. + * + * @param pipelinePolicy The retry policy for service requests. + * @return The updated FileServiceClientBuilder object. + * @throws NullPointerException If {@code pipelinePolicy} is {@code null}. + */ + public FileServiceClientBuilder addPolicy(HttpPipelinePolicy pipelinePolicy) { + Objects.requireNonNull(pipelinePolicy); + this.policies.add(pipelinePolicy); + return this; + } + + /** + * Sets the logging level for HTTP requests and responses. + * + * @param logLevel The amount of logging output when sending and receiving HTTP requests/responses. + * @return The updated FileServiceClientBuilder object. + */ + public FileServiceClientBuilder httpLogDetailLevel(HttpLogDetailLevel logLevel) { + this.logLevel = logLevel; + return this; + } + + /** + * Sets the HTTP pipeline to use for the service client. + * + * If {@code pipeline} is set, all other settings are ignored, aside from {@link FileServiceClientBuilder#endpoint(String) endpoint} + * when building clients. + * + * @param pipeline The HTTP pipeline to use for sending service requests and receiving responses. + * @return The updated FileServiceClientBuilder object. + * @throws NullPointerException If {@code pipeline} is {@code null}. + */ + public FileServiceClientBuilder pipeline(HttpPipeline pipeline) { + this.pipeline = Objects.requireNonNull(pipeline); + return this; + } + + /** + * Sets the configuration store that is used during construction of the service client. + * + * The default configuration store is a clone of the {@link ConfigurationManager#getConfiguration() global + * configuration store}, use {@link Configuration#NONE} to bypass using configuration settings during construction. + * + * @param configuration The configuration store used to + * @return The updated FileServiceClientBuilder object. + * @throws NullPointerException If {@code configuration} is {@code null}. + */ + public FileServiceClientBuilder configuration(Configuration configuration) { + this.configuration = Objects.requireNonNull(configuration); + return this; + } } diff --git a/storage/client/file/src/main/java/com/azure/storage/file/ShareAsyncClient.java b/storage/client/file/src/main/java/com/azure/storage/file/ShareAsyncClient.java index d6d1326ba9545..5b95227e1941d 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/ShareAsyncClient.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/ShareAsyncClient.java @@ -3,81 +3,436 @@ 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.DateTimeRfc1123; +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.ShareCreateSnapshotHeaders; +import com.azure.storage.file.models.ShareGetPropertiesHeaders; import com.azure.storage.file.models.ShareInfo; import com.azure.storage.file.models.ShareProperties; import com.azure.storage.file.models.ShareSnapshotInfo; import com.azure.storage.file.models.ShareStatistics; +import com.azure.storage.file.models.SharesCreateSnapshotResponse; +import com.azure.storage.file.models.SharesGetPropertiesResponse; +import com.azure.storage.file.models.SharesGetStatisticsResponse; import com.azure.storage.file.models.SignedIdentifier; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - +import com.azure.storage.file.models.StorageErrorException; +import java.net.MalformedURLException; +import java.net.URL; +import java.time.OffsetDateTime; import java.util.List; import java.util.Map; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +/** + * This class provides a azureFileStorageClient that contains all the operations for interacting with a share in Azure Storage Share. + * Operations allowed by the azureFileStorageClient are creating and deleting the share, creating snapshots for the share, creating and + * deleting directories in the share and retrieving and updating properties metadata and access policies of the share. + * + *

                  Instantiating 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 Mono> create(Map metadata, int quotaInGB) { - throw new UnsupportedOperationException(); + /** + * Creates the share in the storage account. + * + *

                  Code 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 Mono> create() { + return create(null, null); } + /** + * Creates the share in the storage account with the specified metadata and quota. + * + *

                  Code 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 Mono> create(Map metadata, Integer quotaInGB) { + return azureFileStorageClient.shares().createWithRestResponseAsync(shareName, null, metadata, quotaInGB, Context.NONE) + .map(this::mapToShareInfoResponse); + } + + /** + * Creates a snapshot of the share with the same metadata associated to the share at the time of creation. + * + *

                  Code 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 Mono> createSnapshot() { + return createSnapshot(null); + } + + /** + * Creates a snapshot of the share with the metadata that was passed associated to the snapshot. + * + *

                  Code 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 Mono> createSnapshot(Map metadata) { - throw new UnsupportedOperationException(); + return azureFileStorageClient.shares().createSnapshotWithRestResponseAsync(shareName, null, metadata, Context.NONE) + .map(this::mapCreateSnapshotResponse); } - public Mono delete(String shareSnapshot) { - throw new UnsupportedOperationException(); + /** + * Deletes the share in the storage account + * + *

                  Code 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 Mono delete() { + return azureFileStorageClient.shares().deleteWithRestResponseAsync(shareName, snapshot, null, null, Context.NONE) + .map(VoidResponse::new); } - public Mono> getProperties(String shareSnapshot) { - throw new UnsupportedOperationException(); + /** + * Retrieves the properties of the share, these include the metadata associated to it and the quota that the share + * is restricted to. + * + *

                  Code 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 Mono> getProperties() { + return azureFileStorageClient.shares().getPropertiesWithRestResponseAsync(shareName, snapshot, null, Context.NONE) + .map(this::mapGetPropertiesResponse); } + /** + * Sets the maximum size in GB that the share is allowed to grow. + * + *

                  Code 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 Mono> setQuota(int quotaInGB) { - throw new UnsupportedOperationException(); + return azureFileStorageClient.shares().setQuotaWithRestResponseAsync(shareName, null, quotaInGB, Context.NONE) + .map(this::mapToShareInfoResponse); } + /** + * Sets the user-defined metadata to associate to the share. + * + *

                  If {@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 Mono> setMetadata(Map metadata) { - throw new UnsupportedOperationException(); + return azureFileStorageClient.shares().setMetadataWithRestResponseAsync(shareName, null, metadata, Context.NONE) + .map(this::mapToShareInfoResponse); } - public Flux listAccessPolicy() { - throw new UnsupportedOperationException(); + /** + * Retrieves stored access policies specified for the share. + * + *

                  Code 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 Flux getAccessPolicy() { + return azureFileStorageClient.shares().getAccessPolicyWithRestResponseAsync(shareName, Context.NONE) + .flatMapMany(response -> Flux.fromIterable(response.value())); } + + /** + * Sets stored access policies for the share. + * + *

                  Code 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 Mono> setAccessPolicy(List permissions) { - throw new UnsupportedOperationException(); + return azureFileStorageClient.shares().setAccessPolicyWithRestResponseAsync(shareName, permissions, null, Context.NONE) + .map(this::mapToShareInfoResponse); } + /** + * Retrieves storage statistics about the share. + * + *

                  Code Samples

                  + * + *

                  Retrieve the storage statistics

                  + * + * {@codesnippet com.azure.storage.file.shareAsyncClient.getStatistics} + * + * @return the storage statistics of the share + */ public Mono> getStatistics() { - throw new UnsupportedOperationException(); + return azureFileStorageClient.shares().getStatisticsWithRestResponseAsync(shareName, Context.NONE) + .map(this::mapGetStatisticsResponse); + } + + /** + * Creates the directory in the share with the given name. + * + *

                  Code 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 Mono> createDirectory(String directoryName) { + return createDirectory(directoryName, null); } + /** + * Creates the directory in the share with the given name and associates the passed metadata to it. + * + *

                  Code 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 Mono> createDirectory(String directoryName, Map metadata) { - throw new UnsupportedOperationException(); + DirectoryAsyncClient directoryAsyncClient = getDirectoryClient(directoryName); + return directoryAsyncClient.create(metadata).map(response -> new SimpleResponse<>(response, directoryAsyncClient)); } + /** + * Deletes the specified directory in the share. + * + *

                  Code 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 Mono deleteDirectory(String directoryName) { - throw new UnsupportedOperationException(); + return getDirectoryClient(directoryName).delete().map(VoidResponse::new); + } + + /** + * Get snapshot id which attached to {@link ShareAsyncClient}. + * Return {@code null} if no snapshot id attached. + * + *

                  Code 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 Response mapToShareInfoResponse(Response response) { + String eTag = response.headers().value("ETag"); + OffsetDateTime lastModified = new DateTimeRfc1123(response.headers().value("Last-Modified")).dateTime(); + + return new SimpleResponse<>(response.request(), response.statusCode(), response.headers(), new ShareInfo(eTag, lastModified)); + } + + private Response mapCreateSnapshotResponse(SharesCreateSnapshotResponse response) { + ShareCreateSnapshotHeaders headers = response.deserializedHeaders(); + ShareSnapshotInfo snapshotInfo = new ShareSnapshotInfo(headers.snapshot(), headers.eTag(), headers.lastModified()); + + return new SimpleResponse<>(response.request(), response.statusCode(), response.headers(), snapshotInfo); + } + + private Response mapGetPropertiesResponse(SharesGetPropertiesResponse response) { + ShareGetPropertiesHeaders headers = response.deserializedHeaders(); + ShareProperties shareProperties = new ShareProperties().quota(headers.quota()) + .etag(headers.eTag()) + .lastModified(headers.lastModified()) + .metadata(headers.metadata()); + + return new SimpleResponse<>(response.request(), response.statusCode(), response.headers(), shareProperties); + } + + private Response mapGetStatisticsResponse(SharesGetStatisticsResponse response) { + ShareStatistics shareStatistics = new ShareStatistics(response.value().shareUsageBytes() / 1024); + + return new SimpleResponse<>(response.request(), response.statusCode(), response.headers(), shareStatistics); } } diff --git a/storage/client/file/src/main/java/com/azure/storage/file/ShareClient.java b/storage/client/file/src/main/java/com/azure/storage/file/ShareClient.java index 17ad31b4aa504..2d5c1859eee25 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/ShareClient.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/ShareClient.java @@ -1,82 +1,349 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + package com.azure.storage.file; import com.azure.core.http.rest.Response; +import com.azure.core.http.rest.SimpleResponse; import com.azure.core.http.rest.VoidResponse; +import com.azure.storage.common.credentials.SASTokenCredential; +import com.azure.storage.common.credentials.SharedKeyCredential; import com.azure.storage.file.models.ShareInfo; import com.azure.storage.file.models.ShareProperties; import com.azure.storage.file.models.ShareSnapshotInfo; import com.azure.storage.file.models.ShareStatistics; import com.azure.storage.file.models.SignedIdentifier; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - +import com.azure.storage.file.models.StorageErrorException; +import java.net.URL; import java.util.List; import java.util.Map; +/** + * This class provides a client that contains all the operations for interacting with a share in Azure Storage Share. + * Operations allowed by the client are creating and deleting the share, creating snapshots for the share, creating and + * deleting directories in the share and retrieving and updating properties metadata and access policies of the share. + * + *

                  Instantiating 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 Response create() { + return create(null, null); } - public Mono> create(Map metadata, int quotaInGB) { - throw new UnsupportedOperationException(); + /** + * Creates the share in the storage account with the specified metadata and quota. + * + *

                  Code 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 Response create(Map metadata, Integer quotaInGB) { + return client.create(metadata, quotaInGB).block(); } - public Mono> createSnapshot(Map metadata) { - throw new UnsupportedOperationException(); + /** + * Creates a snapshot of the share with the same metadata associated to the share at the time of creation. + * + *

                  Code 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 Response createSnapshot() { + return createSnapshot(null); } - public Mono delete(String shareSnapshot) { - throw new UnsupportedOperationException(); + /** + * Creates a snapshot of the share with the metadata that was passed associated to the snapshot. + * + *

                  Code 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 createSnapshot(Map metadata) { + return client.createSnapshot(metadata).block(); } - public Mono> getProperties(String shareSnapshot) { - throw new UnsupportedOperationException(); + /** + * Deletes the share in the storage account + * + *

                  Code Samples

                  + * + *

                  Delete the share

                  + * + * {@codesnippet com.azure.storage.file.shareClient.delete} + * + * @return A response that only contains headers and response status code + * @throws StorageErrorException If the share doesn't exist + */ + public VoidResponse delete() { + return client.delete().block(); } - public Mono> setQuota(int quotaInGB) { - throw new UnsupportedOperationException(); + /** + * Retrieves the properties of the share, these include the metadata associated to it and the quota that the share + * is restricted to. + * + *

                  Code Samples

                  + * + *

                  Retrieve the share properties

                  + * + * {@codesnippet com.azure.storage.file.shareClient.getProperties} + * + * @return the properties of the share + * @throws StorageErrorException If the share doesn't exist + */ + public Response getProperties() { + return client.getProperties().block(); } - public Mono> setMetadata(Map metadata) { - throw new UnsupportedOperationException(); + /** + * Sets the maximum size in GB that the share is allowed to grow. + * + *

                  Code Samples

                  + * + *

                  Set the quota to 1024 GB

                  + * + * {@codesnippet com.azure.storage.file.shareClient.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 Response setQuota(int quotaInGB) { + return client.setQuota(quotaInGB).block(); } - public Flux listAccessPolicy() { - throw new UnsupportedOperationException(); + /** + * Sets the user-defined metadata to associate to the share. + * + *

                  If {@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.shareClient.setMetadata#map} + * + *

                  Clear the metadata of the share

                  + * + * {@codesnippet com.azure.storage.file.shareClient.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 Response setMetadata(Map metadata) { + return client.setMetadata(metadata).block(); } - public Mono> setAccessPolicy(List permissions) { - throw new UnsupportedOperationException(); + + /** + * Retrieves stored access policies specified for the share. + * + *

                  Code Samples

                  + * + *

                  List the stored access policies

                  + * + * {@codesnippet com.azure.storage.file.shareClient.getAccessPolicy} + * + * @return The stored access policies specified on the queue. + * @throws StorageErrorException If the share doesn't exist + */ + public Iterable getAccessPolicy() { + return client.getAccessPolicy().toIterable(); + } + + /** + * Sets stored access policies for the share. + * + *

                  Code Samples

                  + * + *

                  Set a read only stored access policy

                  + * + * {@codesnippet com.azure.storage.file.shareClient.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 Response setAccessPolicy(List permissions) { + return client.setAccessPolicy(permissions).block(); + } + + /** + * Retrieves storage statistics about the share. + * + *

                  Code Samples

                  + * + *

                  Retrieve the storage statistics

                  + * + * {@codesnippet com.azure.storage.file.shareClient.getStatistics} + * + * @return the storage statistics of the share + */ + public Response getStatistics() { + return client.getStatistics().block(); + } + + /** + * Creates the directory in the share with the given name. + * + *

                  Code Samples

                  + * + *

                  Create the directory "documents"

                  + * + * {@codesnippet com.azure.storage.file.shareClient.createDirectory#string} + * + * @param directoryName Name of the directory + * @return A response containing a {@link DirectoryClient} 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 Response createDirectory(String directoryName) { + return createDirectory(directoryName, null); } - public Mono> getStatistics() { - throw new UnsupportedOperationException(); + /** + * Creates the directory in the share with the given name and associates the passed metadata to it. + * + *

                  Code Samples

                  + * + *

                  Create the directory "documents" with metadata "directory:metadata"

                  + * + * {@codesnippet com.azure.storage.file.shareClient.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 Response createDirectory(String directoryName, Map metadata) { + DirectoryClient directoryClient = getDirectoryClient(directoryName); + return new SimpleResponse<>(directoryClient.create(metadata), directoryClient); } - public Mono> createDirectory(String directoryName, Map metadata) { - throw new UnsupportedOperationException(); + /** + * Deletes the specified directory in the share. + * + *

                  Code Samples

                  + * + *

                  Delete the directory "empty"

                  + * + * {@codesnippet com.azure.storage.file.shareClient.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 VoidResponse deleteDirectory(String directoryName) { + return client.deleteDirectory(directoryName).block(); } - public Mono deleteDirectory(String directoryName) { - throw new UnsupportedOperationException(); + /** + * Get snapshot id which attached to {@link ShareClient}. + * Return {@code null} if no snapshot id attached. + * + *

                  Code Samples

                  + * + *

                  Get the share snapshot id.

                  + * + * {@codesnippet com.azure.storage.file.shareClient.getSnapshotId} + * + * @return The snapshot id which is a unique {@code DateTime} value that identifies the share snapshot to its base share. + */ + public String getSnapshotId() { + return client.getSnapshotId(); } } diff --git a/storage/client/file/src/main/java/com/azure/storage/file/ShareClientBuilder.java b/storage/client/file/src/main/java/com/azure/storage/file/ShareClientBuilder.java index 5ab4e37ddcd3e..ec6d06ddee182 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/ShareClientBuilder.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/ShareClientBuilder.java @@ -3,7 +3,343 @@ 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 ShareClient ShareClients} + * and {@link ShareAsyncClient SahreAsyncClients}, calling {@link ShareClientBuilder#buildClient() buildClient} + * constructs an instance of ShareClient and calling {@link ShareClientBuilder#buildAsyncClient() buildAsyncClient} + * constructs an instance of SahreAsyncClient. + * + *

                  The client needs the endpoint of the Azure Storage File service, name of the share, and authorization credential. + * {@link ShareClientBuilder#endpoint(String) endpoint} gives the builder the endpoint and may give the builder the + * {@link ShareClientBuilder#shareName(String) shareName} and a {@link SASTokenCredential} that authorizes the client.

                  + * + *

                  Instantiating a synchronous Share Client with SAS token

                  + * {@codesnippet com.azure.storage.file.shareClient.instantiation.sastoken} + * + *

                  Instantiating an Asynchronous Share Client with SAS token

                  + * {@codesnippet com.azure.storage.file.shareAsyncClient.instantiation.sastoken} + * + *

                  If the {@code endpoint} doesn't contain the query parameters to construct a {@code SASTokenCredential} they may + * be set using {@link ShareClientBuilder#credential(SASTokenCredential) credential}.

                  + * + * {@codesnippet com.azure.storage.file.shareClient.instantiation.credential} + * + * {@codesnippet com.azure.storage.file.shareAsyncClient.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 ShareClientBuilder#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 Share Client with connection string.

                  + * {@codesnippet com.azure.storage.file.shareClient.instantiation.connectionstring} + * + *

                  Instantiating an Asynchronous Share Client with connection string.

                  + * {@codesnippet com.azure.storage.file.shareAsyncClient.instantiation.connectionstring} + * + * @see ShareClient + * @see ShareAsyncClient + * @see SASTokenCredential + * @see SharedKeyCredential + */ public class ShareClientBuilder { + private static final String ACCOUNT_NAME = "accountname"; + private final List policies; + + private URL endpoint; + private SASTokenCredential sasTokenCredential; + private SharedKeyCredential sharedKeyCredential; + private String shareName; + private String snapshot; + private HttpClient httpClient; + private HttpPipeline pipeline; + private HttpLogDetailLevel logLevel; + private RetryPolicy retryPolicy; + private Configuration configuration; + + /** + * Creates a builder instance that is able to configure and construct {@link ShareClient ShareClients} + * and {@link ShareAsyncClient ShareAsyncClients}. + */ + public ShareClientBuilder() { + retryPolicy = new RetryPolicy(); + logLevel = HttpLogDetailLevel.NONE; + policies = new ArrayList<>(); + configuration = ConfigurationManager.getConfiguration(); + } + + /** + * Creates a {@link ShareAsyncClient} based on options set in the builder. Every time {@code buildAsyncClient()} is + * called a new instance of {@link ShareAsyncClient} is created. + * + *

                  + * If {@link ShareClientBuilder#pipeline(HttpPipeline) pipeline} is set, then the {@code pipeline} and + * {@link ShareClientBuilder#endpoint(String) endpoint} are used to create the + * {@link ShareAsyncClient 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}. + * @throws IllegalArgumentException If neither a {@link SharedKeyCredential} or {@link SASTokenCredential} has been set. + */ + public ShareAsyncClient buildAsyncClient() { + Objects.requireNonNull(shareName); + + if (pipeline != null) { + return new ShareAsyncClient(endpoint, pipeline, shareName, 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 policies = new ArrayList<>(); + + policies.add(new UserAgentPolicy(FileConfiguration.NAME, FileConfiguration.VERSION, configuration)); + policies.add(new RequestIdPolicy()); + policies.add(new AddDatePolicy()); + + if (sharedKeyCredential != null) { + policies.add(new SharedKeyCredentialPolicy(sharedKeyCredential)); + } else { + policies.add(new SASTokenCredentialPolicy(sasTokenCredential)); + } + + HttpPolicyProviders.addBeforeRetryPolicies(policies); + + policies.add(retryPolicy); + + policies.addAll(this.policies); + HttpPolicyProviders.addAfterRetryPolicies(policies); + policies.add(new HttpLoggingPolicy(logLevel)); + + HttpPipeline pipeline = HttpPipeline.builder() + .policies(policies.toArray(new HttpPipelinePolicy[0])) + .httpClient(httpClient) + .build(); + + return new ShareAsyncClient(endpoint, pipeline, shareName, snapshot); + } + + /** + * Creates a {@link ShareClient} based on options set in the builder. Every time {@code buildClient()} is + * called a new instance of {@link ShareClient} is created. + * + *

                  + * If {@link ShareClientBuilder#pipeline(HttpPipeline) pipeline} is set, then the {@code pipeline} and + * {@link ShareClientBuilder#endpoint(String) endpoint} are used to create the + * {@link ShareClient client}. All other builder settings are ignored. + *

                  + * + * @return A ShareClient with the options set from the builder. + * @throws NullPointerException If {@code endpoint} or {@code shareName} is {@code null}. + * @throws IllegalStateException If neither a {@link SharedKeyCredential} or {@link SASTokenCredential} has been set. + */ + public ShareClient buildClient() { + return new ShareClient(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.

                  + * + *

                  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 ShareClientBuilder object + * @throws IllegalArgumentException If {@code endpoint} is {@code null} or is an invalid URL + */ + public ShareClientBuilder 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 File service. + * + * @param credential SAS token credential generated from the Storage account that authorizes requests + * @return the updated ShareClientBuilder object + * @throws NullPointerException If {@code credential} is {@code null}. + */ + public ShareClientBuilder 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 ShareClientBuilder 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 ShareClientBuilder object + * @throws NullPointerException If {@code connectionString} is {@code null}. + */ + public ShareClientBuilder connectionString(String connectionString) { + Objects.requireNonNull(connectionString); + this.sharedKeyCredential = SharedKeyCredential.fromConnectionString(connectionString); + getEndPointFromConnectionString(connectionString); + return this; + } + + private void getEndPointFromConnectionString(String connectionString) { + Map connectionStringPieces = new HashMap<>(); + for (String connectionStringPiece : connectionString.split(";")) { + String[] kvp = connectionStringPiece.split("=", 2); + connectionStringPieces.put(kvp[0].toLowerCase(Locale.ROOT), kvp[1]); + } + String accountName = connectionStringPieces.get(ACCOUNT_NAME); + try { + this.endpoint = new URL(String.format("https://%s.file.core.windows.net", accountName)); + } catch (MalformedURLException e) { + throw new IllegalArgumentException(String.format("There is no valid endpoint for the connection string. " + + "Connection String: %s", connectionString)); + } + } + + /** + * Sets the share that the constructed clients will interact with + * + * @param shareName Name of the share + * @return the updated ShareClientBuilder object + * @throws NullPointerException If {@code shareName} is {@code null}. + */ + public ShareClientBuilder shareName(String shareName) { + this.shareName = Objects.requireNonNull(shareName); + return this; + } + + /** + * 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 ShareClientBuilder object + * @throws NullPointerException If {@code snapshot} is {@code null}. + */ + public ShareClientBuilder snapshot(String snapshot) { + this.snapshot = Objects.requireNonNull(snapshot); + return this; + } + + /** + * Sets the HTTP client to use for sending and receiving requests to and from the service. + * + * @param httpClient The HTTP client to use for requests. + * @return The updated ShareClientBuilder object. + * @throws NullPointerException If {@code httpClient} is {@code null}. + */ + public ShareClientBuilder httpClient(HttpClient httpClient) { + this.httpClient = Objects.requireNonNull(httpClient); + return this; + } + + /** + * Adds a policy to the set of existing policies that are executed after the {@link RetryPolicy}. + * + * @param pipelinePolicy The retry policy for service requests. + * @return The updated ShareClientBuilder object. + * @throws NullPointerException If {@code pipelinePolicy} is {@code null}. + */ + public ShareClientBuilder addPolicy(HttpPipelinePolicy pipelinePolicy) { + Objects.requireNonNull(pipelinePolicy); + this.policies.add(pipelinePolicy); + return this; + } + + /** + * Sets the logging level for HTTP requests and responses. + * + * @param logLevel The amount of logging output when sending and receiving HTTP requests/responses. + * @return The updated ShareClientBuilder object. + */ + public ShareClientBuilder httpLogDetailLevel(HttpLogDetailLevel logLevel) { + this.logLevel = logLevel; + return this; + } + + /** + * Sets the HTTP pipeline to use for the service client. + * + *

                  If {@code pipeline} is set, all other settings are ignored, aside from {@link ShareClientBuilder#endpoint(String) endpoint}, + * {@link ShareClientBuilder#shareName(String) shareName}, and {@link ShareClientBuilder#snapshot(String) snaphotShot} + * when building clients.

                  + * + * @param pipeline The HTTP pipeline to use for sending service requests and receiving responses. + * @return The updated ShareClientBuilder object. + * @throws NullPointerException If {@code pipeline} is {@code null}. + */ + public ShareClientBuilder pipeline(HttpPipeline pipeline) { + this.pipeline = Objects.requireNonNull(pipeline); + return this; + } - // connectionString, shareName, FileClientOptions, withSnapshot, SharedKeyCredential, + /** + * Sets the configuration store that is used during construction of the service client. + * + * The default configuration store is a clone of the {@link ConfigurationManager#getConfiguration() global + * configuration store}, use {@link Configuration#NONE} to bypass using configuration settings during construction. + * + * @param configuration The configuration store used to + * @return The updated ShareClientBuilder object. + * @throws NullPointerException If {@code configuration} is {@code null}. + */ + public ShareClientBuilder configuration(Configuration configuration) { + this.configuration = Objects.requireNonNull(configuration); + return this; + } } diff --git a/storage/client/file/src/main/java/com/azure/storage/file/implementation/AzureFileStorageBuilder.java b/storage/client/file/src/main/java/com/azure/storage/file/implementation/AzureFileStorageBuilder.java index 6dced97e93c08..53903ed5f4c8d 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/implementation/AzureFileStorageBuilder.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/implementation/AzureFileStorageBuilder.java @@ -72,9 +72,9 @@ public AzureFileStorageImpl build() { this.pipeline = RestProxy.createDefaultPipeline(); } AzureFileStorageImpl client = new AzureFileStorageImpl(pipeline); - if (this.version != null) { - client.version(this.version); - } + + client.version(this.version); + if (this.url != null) { client.url(this.url); } diff --git a/storage/client/file/src/main/java/com/azure/storage/file/implementation/DirectorysImpl.java b/storage/client/file/src/main/java/com/azure/storage/file/implementation/DirectorysImpl.java index 4e3f44c781ef9..b2afc6d343585 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/implementation/DirectorysImpl.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/implementation/DirectorysImpl.java @@ -11,6 +11,7 @@ import com.azure.core.annotations.Host; import com.azure.core.annotations.HostParam; import com.azure.core.annotations.PUT; +import com.azure.core.annotations.PathParam; import com.azure.core.annotations.QueryParam; import com.azure.core.annotations.Service; import com.azure.core.annotations.UnexpectedResponseExceptionType; @@ -23,9 +24,9 @@ import com.azure.storage.file.models.DirectorysListFilesAndDirectoriesSegmentResponse; import com.azure.storage.file.models.DirectorysListHandlesResponse; import com.azure.storage.file.models.DirectorysSetMetadataResponse; +import com.azure.storage.file.models.FilesDeleteResponse; import com.azure.storage.file.models.StorageErrorException; import reactor.core.publisher.Mono; - import java.util.Map; /** @@ -49,7 +50,7 @@ public final class DirectorysImpl { * @param client the instance of the service client containing this operation class. */ public DirectorysImpl(AzureFileStorageImpl client) { - this.service = RestProxy.create(DirectorysService.class, client); + this.service = RestProxy.create(DirectorysService.class, client.httpPipeline()); this.client = client; } @@ -58,164 +59,235 @@ public DirectorysImpl(AzureFileStorageImpl client) { * proxy service to perform REST calls. */ @Host("{url}") - @Service("Storage Files Directory") + @Service("Storage File Directories") private interface DirectorysService { @PUT("{shareName}/{directory}") @ExpectedResponses({201}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono create(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-meta-") Map metadata, @HeaderParam("x-ms-version") String version, @QueryParam("restype") String restype, Context context); + Mono create(@HostParam("url") String url, @PathParam("shareName") String shareName, @PathParam("directory") String directoryName, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-meta-") Map metadata, @HeaderParam("x-ms-version") String version, @QueryParam("restype") String restype, Context context); @GET("{shareName}/{directory}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono getProperties(@HostParam("url") String url, @QueryParam("sharesnapshot") String sharesnapshot, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @QueryParam("restype") String restype, Context context); + Mono getProperties(@HostParam("url") String url, @PathParam("shareName") String shareName, @PathParam("directory") String directoryName, @QueryParam("sharesnapshot") String sharesnapshot, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @QueryParam("restype") String restype, Context context); @DELETE("{shareName}/{directory}") @ExpectedResponses({202}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono delete(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @QueryParam("restype") String restype, Context context); + Mono delete(@HostParam("url") String url, @PathParam("shareName") String shareName, @PathParam("directory") String directoryName, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @QueryParam("restype") String restype, Context context); + + @DELETE("{shareName}/{directory}/{fileName}") + @ExpectedResponses({202}) + @UnexpectedResponseExceptionType(StorageErrorException.class) + Mono delete(@HostParam("url") String url, @PathParam("shareName") String shareName, @PathParam("directory") String directoryName, @PathParam("fileName") String fileName, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @QueryParam("restype") String restype, Context context); @PUT("{shareName}/{directory}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono setMetadata(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-meta-") Map metadata, @HeaderParam("x-ms-version") String version, @QueryParam("restype") String restype, @QueryParam("comp") String comp, Context context); + Mono setMetadata(@HostParam("url") String url, @PathParam("shareName") String shareName, @PathParam("directory") String directoryName, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-meta-") Map metadata, @HeaderParam("x-ms-version") String version, @QueryParam("restype") String restype, @QueryParam("comp") String comp, Context context); @GET("{shareName}/{directory}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono listFilesAndDirectoriesSegment(@HostParam("url") String url, @QueryParam("prefix") String prefix, @QueryParam("sharesnapshot") String sharesnapshot, @QueryParam("marker") String marker, @QueryParam("maxresults") Integer maxresults, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @QueryParam("restype") String restype, @QueryParam("comp") String comp, Context context); + Mono listFilesAndDirectoriesSegment(@HostParam("url") String url, @PathParam("shareName") String shareName, @PathParam("directory") String directoryName, @QueryParam("prefix") String prefix, @QueryParam("sharesnapshot") String sharesnapshot, @QueryParam("marker") String marker, @QueryParam("maxresults") Integer maxresults, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @QueryParam("restype") String restype, @QueryParam("comp") String comp, Context context); @GET("{shareName}/{directory}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono listHandles(@HostParam("url") String url, @QueryParam("marker") String marker, @QueryParam("maxresults") Integer maxresults, @QueryParam("timeout") Integer timeout, @QueryParam("sharesnapshot") String sharesnapshot, @HeaderParam("x-ms-recursive") Boolean recursive, @HeaderParam("x-ms-version") String version, @QueryParam("comp") String comp, Context context); + Mono listHandles(@HostParam("url") String url, @PathParam("shareName") String shareName, @PathParam("directory") String directoryName, @QueryParam("marker") String marker, @QueryParam("maxresults") Integer maxresults, @QueryParam("timeout") Integer timeout, @QueryParam("sharesnapshot") String sharesnapshot, @HeaderParam("x-ms-recursive") Boolean recursive, @HeaderParam("x-ms-version") String version, @QueryParam("comp") String comp, Context context); @PUT("{shareName}/{directory}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono forceCloseHandles(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @QueryParam("marker") String marker, @QueryParam("sharesnapshot") String sharesnapshot, @HeaderParam("x-ms-handle-id") String handleId, @HeaderParam("x-ms-recursive") Boolean recursive, @HeaderParam("x-ms-version") String version, @QueryParam("comp") String comp, Context context); + Mono forceCloseHandles(@HostParam("url") String url, @PathParam("shareName") String shareName, @PathParam("directory") String directoryName, @QueryParam("timeout") Integer timeout, @QueryParam("marker") String marker, @QueryParam("sharesnapshot") String sharesnapshot, @HeaderParam("x-ms-handle-id") String handleId, @HeaderParam("x-ms-recursive") Boolean recursive, @HeaderParam("x-ms-version") String version, @QueryParam("comp") String comp, Context context); } /** * Creates a new directory under the specified share or parent directory. * + * @param shareName Name of the share. + * @param directoryName Path to the directory. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono createWithRestResponseAsync(Context context) { + public Mono createWithRestResponseAsync(String shareName, String directoryName, Context context) { final Integer timeout = null; final Map metadata = null; final String restype = "directory"; - return service.create(this.client.url(), timeout, metadata, this.client.version(), restype, context); + return service.create(this.client.url(), shareName, directoryName, timeout, metadata, this.client.version(), restype, context); } /** * Creates a new directory under the specified share or parent directory. * + * @param shareName Name of the share. + * @param directoryName Path to the directory. * @param timeout The timeout parameter is expressed in seconds. For more information, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN">Setting Timeouts for File Service Operations.</a>. * @param metadata A name-value pair to associate with a file storage object. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono createWithRestResponseAsync(Integer timeout, Map metadata, Context context) { + public Mono createWithRestResponseAsync(String shareName, String directoryName, Integer timeout, Map metadata, Context context) { final String restype = "directory"; - return service.create(this.client.url(), timeout, metadata, this.client.version(), restype, context); + return service.create(this.client.url(), shareName, directoryName, timeout, metadata, this.client.version(), restype, context); + } + + /** + * Creates a new directory under the specified share or parent directory. + * + * @param shareName Name of the share. + * @param directoryName Path to the directory. + * @param metadata A name-value pair to associate with a file storage object. + * @param context The context to associate with this operation. + * @throws IllegalArgumentException thrown if parameters fail the validation. + * @return a Mono which performs the network request upon subscription. + */ + public Mono createSubDirectoryWithRestResponseAsync(String shareName, String directoryName, Map metadata, Context context) { + final Integer timeout = null; + final String restype = "directory"; + return service.create(this.client.url(), shareName, directoryName, timeout, metadata, this.client.version(), restype, context); } /** * Returns all system properties for the specified directory, and can also be used to check the existence of a directory. The data returned does not include the files in the directory or any subdirectories. * + * @param shareName Name of the share. + * @param directoryName Path to the directory. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono getPropertiesWithRestResponseAsync(Context context) { + public Mono getPropertiesWithRestResponseAsync(String shareName, String directoryName, Context context) { final String sharesnapshot = null; final Integer timeout = null; final String restype = "directory"; - return service.getProperties(this.client.url(), sharesnapshot, timeout, this.client.version(), restype, context); + return service.getProperties(this.client.url(), shareName, directoryName, sharesnapshot, timeout, this.client.version(), restype, context); } /** * Returns all system properties for the specified directory, and can also be used to check the existence of a directory. The data returned does not include the files in the directory or any subdirectories. * + * @param shareName Name of the share. + * @param directoryName Path to the directory. * @param sharesnapshot The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. * @param timeout The timeout parameter is expressed in seconds. For more information, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN">Setting Timeouts for File Service Operations.</a>. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono getPropertiesWithRestResponseAsync(String sharesnapshot, Integer timeout, Context context) { + public Mono getPropertiesWithRestResponseAsync(String shareName, String directoryName, String sharesnapshot, Integer timeout, Context context) { final String restype = "directory"; - return service.getProperties(this.client.url(), sharesnapshot, timeout, this.client.version(), restype, context); + return service.getProperties(this.client.url(), shareName, directoryName, sharesnapshot, timeout, this.client.version(), restype, context); } /** * Removes the specified empty directory. Note that the directory must be empty before it can be deleted. * + * @param shareName Name of the share. + * @param directoryName Path to the directory. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono deleteWithRestResponseAsync(Context context) { + public Mono deleteWithRestResponseAsync(String shareName, String directoryName, Context context) { final Integer timeout = null; final String restype = "directory"; - return service.delete(this.client.url(), timeout, this.client.version(), restype, context); + return service.delete(this.client.url(), shareName, directoryName, timeout, this.client.version(), restype, context); + } + + /** + * Removes the specified empty directory. Note that the directory must be empty before it can be deleted. + * + * @param shareName Name of the share. + * @param directoryName Path to the directory. + * @param timeout The timeout parameter is expressed in seconds. For more information, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN">Setting Timeouts for File Service Operations.</a>. + * @param context The context to associate with this operation. + * @throws IllegalArgumentException thrown if parameters fail the validation. + * @return a Mono which performs the network request upon subscription. + */ + public Mono deleteWithRestResponseAsync(String shareName, String directoryName, Integer timeout, Context context) { + final String restype = "directory"; + return service.delete(this.client.url(), shareName, directoryName, timeout, this.client.version(), restype, context); } + /** * Removes the specified empty directory. Note that the directory must be empty before it can be deleted. * + * @param shareName Name of the share. + * @param directoryName Path to the directory. + * @param timeout The timeout parameter is expressed in seconds. For more information, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN">Setting Timeouts for File Service Operations.</a>. + * @param context The context to associate with this operation. + * @throws IllegalArgumentException thrown if parameters fail the validation. + * @return a Mono which performs the network request upon subscription. + */ + public Mono deleteSubWithRestResponseAsync(String shareName, String directoryName, Integer timeout, Context context) { + final String restype = "directory"; + return service.delete(this.client.url(), shareName, directoryName, timeout, this.client.version(), restype, context); + } + + /** + * Removes the specified file. + * + * @param shareName Name of the share. + * @param directoryName Path to the directory. + * @param fileName Name of the file. * @param timeout The timeout parameter is expressed in seconds. For more information, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN">Setting Timeouts for File Service Operations.</a>. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono deleteWithRestResponseAsync(Integer timeout, Context context) { + public Mono deleteFileWithRestResponseAsync(String shareName, String directoryName, String fileName, Integer timeout, Context context) { final String restype = "directory"; - return service.delete(this.client.url(), timeout, this.client.version(), restype, context); + return service.delete(this.client.url(), shareName, directoryName, fileName, timeout, this.client.version(), restype, context); } /** * Updates user defined metadata for the specified directory. * + * @param shareName Name of the share. + * @param directoryName Path to the directory. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono setMetadataWithRestResponseAsync(Context context) { + public Mono setMetadataWithRestResponseAsync(String shareName, String directoryName, Context context) { final Integer timeout = null; final Map metadata = null; final String restype = "directory"; final String comp = "metadata"; - return service.setMetadata(this.client.url(), timeout, metadata, this.client.version(), restype, comp, context); + return service.setMetadata(this.client.url(), shareName, directoryName, timeout, metadata, this.client.version(), restype, comp, context); } /** * Updates user defined metadata for the specified directory. * + * @param shareName Name of the share. + * @param directoryName Path to the directory. * @param timeout The timeout parameter is expressed in seconds. For more information, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN">Setting Timeouts for File Service Operations.</a>. * @param metadata A name-value pair to associate with a file storage object. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono setMetadataWithRestResponseAsync(Integer timeout, Map metadata, Context context) { + public Mono setMetadataWithRestResponseAsync(String shareName, String directoryName, Integer timeout, Map metadata, Context context) { final String restype = "directory"; final String comp = "metadata"; - return service.setMetadata(this.client.url(), timeout, metadata, this.client.version(), restype, comp, context); + return service.setMetadata(this.client.url(), shareName, directoryName, timeout, metadata, this.client.version(), restype, comp, context); } /** * Returns a list of files or directories under the specified share or directory. It lists the contents only for a single level of the directory hierarchy. * + * @param shareName Name of the share. + * @param directoryName Path to the directory. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono listFilesAndDirectoriesSegmentWithRestResponseAsync(Context context) { + public Mono listFilesAndDirectoriesSegmentWithRestResponseAsync(String shareName, String directoryName, Context context) { final String prefix = null; final String sharesnapshot = null; final String marker = null; @@ -223,12 +295,14 @@ public Mono listFilesAndDirect final Integer timeout = null; final String restype = "directory"; final String comp = "list"; - return service.listFilesAndDirectoriesSegment(this.client.url(), prefix, sharesnapshot, marker, maxresults, timeout, this.client.version(), restype, comp, context); + return service.listFilesAndDirectoriesSegment(this.client.url(), shareName, directoryName, prefix, sharesnapshot, marker, maxresults, timeout, this.client.version(), restype, comp, context); } /** * Returns a list of files or directories under the specified share or directory. It lists the contents only for a single level of the directory hierarchy. * + * @param shareName Name of the share. + * @param directoryName Path to the directory. * @param prefix Filters the results to return only entries whose name begins with the specified prefix. * @param sharesnapshot The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. * @param marker A string value that identifies the portion of the list to be returned with the next list operation. The operation returns a marker value within the response body if the list returned was not complete. The marker value may then be used in a subsequent call to request the next set of list items. The marker value is opaque to the client. @@ -238,32 +312,36 @@ public Mono listFilesAndDirect * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono listFilesAndDirectoriesSegmentWithRestResponseAsync(String prefix, String sharesnapshot, String marker, Integer maxresults, Integer timeout, Context context) { + public Mono listFilesAndDirectoriesSegmentWithRestResponseAsync(String shareName, String directoryName, String prefix, String sharesnapshot, String marker, Integer maxresults, Integer timeout, Context context) { final String restype = "directory"; final String comp = "list"; - return service.listFilesAndDirectoriesSegment(this.client.url(), prefix, sharesnapshot, marker, maxresults, timeout, this.client.version(), restype, comp, context); + return service.listFilesAndDirectoriesSegment(this.client.url(), shareName, directoryName, prefix, sharesnapshot, marker, maxresults, timeout, this.client.version(), restype, comp, context); } /** * Lists handles for directory. * + * @param shareName Name of the share. + * @param directoryName Path to the directory. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono listHandlesWithRestResponseAsync(Context context) { + public Mono listHandlesWithRestResponseAsync(String shareName, String directoryName, Context context) { final String marker = null; final Integer maxresults = null; final Integer timeout = null; final String sharesnapshot = null; final Boolean recursive = null; final String comp = "listhandles"; - return service.listHandles(this.client.url(), marker, maxresults, timeout, sharesnapshot, recursive, this.client.version(), comp, context); + return service.listHandles(this.client.url(), shareName, directoryName, marker, maxresults, timeout, sharesnapshot, recursive, this.client.version(), comp, context); } /** * Lists handles for directory. * + * @param shareName Name of the share. + * @param directoryName Path to the directory. * @param marker A string value that identifies the portion of the list to be returned with the next list operation. The operation returns a marker value within the response body if the list returned was not complete. The marker value may then be used in a subsequent call to request the next set of list items. The marker value is opaque to the client. * @param maxresults Specifies the maximum number of entries to return. If the request does not specify maxresults, or specifies a value greater than 5,000, the server will return up to 5,000 items. * @param timeout The timeout parameter is expressed in seconds. For more information, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN">Setting Timeouts for File Service Operations.</a>. @@ -273,31 +351,35 @@ public Mono listHandlesWithRestResponseAsync(Cont * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono listHandlesWithRestResponseAsync(String marker, Integer maxresults, Integer timeout, String sharesnapshot, Boolean recursive, Context context) { + public Mono listHandlesWithRestResponseAsync(String shareName, String directoryName, String marker, Integer maxresults, Integer timeout, String sharesnapshot, Boolean recursive, Context context) { final String comp = "listhandles"; - return service.listHandles(this.client.url(), marker, maxresults, timeout, sharesnapshot, recursive, this.client.version(), comp, context); + return service.listHandles(this.client.url(), shareName, directoryName, marker, maxresults, timeout, sharesnapshot, recursive, this.client.version(), comp, context); } /** * Closes all handles open for given directory. * + * @param shareName Name of the share. + * @param directoryName Path to the directory. * @param handleId Specifies handle ID opened on the file or directory to be closed. Asterix (‘*’) is a wildcard that specifies all handles. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono forceCloseHandlesWithRestResponseAsync(String handleId, Context context) { + public Mono forceCloseHandlesWithRestResponseAsync(String shareName, String directoryName, String handleId, Context context) { final Integer timeout = null; final String marker = null; final String sharesnapshot = null; final Boolean recursive = null; final String comp = "forceclosehandles"; - return service.forceCloseHandles(this.client.url(), timeout, marker, sharesnapshot, handleId, recursive, this.client.version(), comp, context); + return service.forceCloseHandles(this.client.url(), shareName, directoryName, timeout, marker, sharesnapshot, handleId, recursive, this.client.version(), comp, context); } /** * Closes all handles open for given directory. * + * @param shareName Name of the share. + * @param directoryName Path to the directory. * @param handleId Specifies handle ID opened on the file or directory to be closed. Asterix (‘*’) is a wildcard that specifies all handles. * @param timeout The timeout parameter is expressed in seconds. For more information, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN">Setting Timeouts for File Service Operations.</a>. * @param marker A string value that identifies the portion of the list to be returned with the next list operation. The operation returns a marker value within the response body if the list returned was not complete. The marker value may then be used in a subsequent call to request the next set of list items. The marker value is opaque to the client. @@ -307,8 +389,8 @@ public Mono forceCloseHandlesWithRestRespon * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono forceCloseHandlesWithRestResponseAsync(String handleId, Integer timeout, String marker, String sharesnapshot, Boolean recursive, Context context) { + public Mono forceCloseHandlesWithRestResponseAsync(String shareName, String directoryName, String handleId, Integer timeout, String marker, String sharesnapshot, Boolean recursive, Context context) { final String comp = "forceclosehandles"; - return service.forceCloseHandles(this.client.url(), timeout, marker, sharesnapshot, handleId, recursive, this.client.version(), comp, context); + return service.forceCloseHandles(this.client.url(), shareName, directoryName, timeout, marker, sharesnapshot, handleId, recursive, this.client.version(), comp, context); } } diff --git a/storage/client/file/src/main/java/com/azure/storage/file/implementation/FilesImpl.java b/storage/client/file/src/main/java/com/azure/storage/file/implementation/FilesImpl.java index ee44ffe4f9830..ad5783b2d1d68 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/implementation/FilesImpl.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/implementation/FilesImpl.java @@ -13,6 +13,7 @@ import com.azure.core.annotations.Host; import com.azure.core.annotations.HostParam; import com.azure.core.annotations.PUT; +import com.azure.core.annotations.PathParam; import com.azure.core.annotations.QueryParam; import com.azure.core.annotations.Service; import com.azure.core.annotations.UnexpectedResponseExceptionType; @@ -61,7 +62,7 @@ public final class FilesImpl { * @param client the instance of the service client containing this operation class. */ public FilesImpl(AzureFileStorageImpl client) { - this.service = RestProxy.create(FilesService.class, client); + this.service = RestProxy.create(FilesService.class, client.httpPipeline()); this.client = client; } @@ -70,77 +71,80 @@ public FilesImpl(AzureFileStorageImpl client) { * proxy service to perform REST calls. */ @Host("{url}") - @Service("Storage Files File") + @Service("Storage File Files") private interface FilesService { - @PUT("{shareName}/{directory}/{fileName}") + @PUT("{shareName}/{filePath}") @ExpectedResponses({201}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono create(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-content-length") long fileContentLength, @HeaderParam("x-ms-type") String fileTypeConstant, @HeaderParam("x-ms-meta-") Map metadata, @HeaderParam("x-ms-content-type") String fileContentType, @HeaderParam("x-ms-content-encoding") String fileContentEncoding, @HeaderParam("x-ms-content-language") String fileContentLanguage, @HeaderParam("x-ms-cache-control") String fileCacheControl, @HeaderParam("x-ms-content-md5") String fileContentMD5, @HeaderParam("x-ms-content-disposition") String fileContentDisposition, Context context); + Mono create(@HostParam("url") String url, @PathParam("shareName") String shareName, @PathParam("filePath") String filePath, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-content-length") long fileContentLength, @HeaderParam("x-ms-type") String fileTypeConstant, @HeaderParam("x-ms-meta-") Map metadata, @HeaderParam("x-ms-content-type") String fileContentType, @HeaderParam("x-ms-content-encoding") String fileContentEncoding, @HeaderParam("x-ms-content-language") String fileContentLanguage, @HeaderParam("x-ms-cache-control") String fileCacheControl, @HeaderParam("x-ms-content-md5") String fileContentMD5, @HeaderParam("x-ms-content-disposition") String fileContentDisposition, Context context); - @GET("{shareName}/{directory}/{fileName}") + @GET("{shareName}/{filePath}") @ExpectedResponses({200, 206}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono download(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-range") String range, @HeaderParam("x-ms-range-get-content-md5") Boolean rangeGetContentMD5, Context context); + Mono download(@HostParam("url") String url, @PathParam("shareName") String shareName, @PathParam("filePath") String filePath, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-range") String range, @HeaderParam("x-ms-range-get-content-md5") Boolean rangeGetContentMD5, Context context); - @HEAD("{shareName}/{directory}/{fileName}") + @HEAD("{shareName}/{filePath}") @ExpectedResponses({200}) - Mono getProperties(@HostParam("url") String url, @QueryParam("sharesnapshot") String sharesnapshot, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, Context context); + @UnexpectedResponseExceptionType(StorageErrorException.class) + Mono getProperties(@HostParam("url") String url, @PathParam("shareName") String shareName, @PathParam("filePath") String filePath, @QueryParam("sharesnapshot") String sharesnapshot, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, Context context); - @DELETE("{shareName}/{directory}/{fileName}") + @DELETE("{shareName}/{filePath}") @ExpectedResponses({202}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono delete(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, Context context); + Mono delete(@HostParam("url") String url, @PathParam("shareName") String shareName, @PathParam("filePath") String filePath, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, Context context); - @PUT("{shareName}/{directory}/{fileName}") + @PUT("{shareName}/{filePath}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono setHTTPHeaders(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-content-length") Long fileContentLength, @QueryParam("comp") String comp, @HeaderParam("x-ms-content-type") String fileContentType, @HeaderParam("x-ms-content-encoding") String fileContentEncoding, @HeaderParam("x-ms-content-language") String fileContentLanguage, @HeaderParam("x-ms-cache-control") String fileCacheControl, @HeaderParam("x-ms-content-md5") String fileContentMD5, @HeaderParam("x-ms-content-disposition") String fileContentDisposition, Context context); + Mono setHTTPHeaders(@HostParam("url") String url, @PathParam("shareName") String shareName, @PathParam("filePath") String filePath, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-content-length") Long fileContentLength, @QueryParam("comp") String comp, @HeaderParam("x-ms-content-type") String fileContentType, @HeaderParam("x-ms-content-encoding") String fileContentEncoding, @HeaderParam("x-ms-content-language") String fileContentLanguage, @HeaderParam("x-ms-cache-control") String fileCacheControl, @HeaderParam("x-ms-content-md5") String fileContentMD5, @HeaderParam("x-ms-content-disposition") String fileContentDisposition, Context context); - @PUT("{shareName}/{directory}/{fileName}") + @PUT("{shareName}/{filePath}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono setMetadata(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-meta-") Map metadata, @HeaderParam("x-ms-version") String version, @QueryParam("comp") String comp, Context context); + Mono setMetadata(@HostParam("url") String url, @PathParam("shareName") String shareName, @PathParam("filePath") String filePath, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-meta-") Map metadata, @HeaderParam("x-ms-version") String version, @QueryParam("comp") String comp, Context context); - @PUT("{shareName}/{directory}/{fileName}") + @PUT("{shareName}/{filePath}") @ExpectedResponses({201}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono uploadRange(@HostParam("url") String url, @BodyParam("application/octet-stream") Flux optionalbody, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-range") String range, @HeaderParam("x-ms-write") FileRangeWriteType fileRangeWrite, @HeaderParam("Content-Length") long contentLength, @HeaderParam("Content-MD5") String contentMD5, @HeaderParam("x-ms-version") String version, @QueryParam("comp") String comp, Context context); + Mono uploadRange(@HostParam("url") String url, @PathParam("shareName") String shareName, @PathParam("filePath") String filePath, @BodyParam("application/octet-stream") Flux optionalbody, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-range") String range, @HeaderParam("x-ms-write") FileRangeWriteType fileRangeWrite, @HeaderParam("Content-Length") long contentLength, @HeaderParam("Content-MD5") String contentMD5, @HeaderParam("x-ms-version") String version, @QueryParam("comp") String comp, Context context); - @GET("{shareName}/{directory}/{fileName}") + @GET("{shareName}/{filePath}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono getRangeList(@HostParam("url") String url, @QueryParam("sharesnapshot") String sharesnapshot, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-range") String range, @QueryParam("comp") String comp, Context context); + Mono getRangeList(@HostParam("url") String url, @PathParam("shareName") String shareName, @PathParam("filePath") String filePath, @QueryParam("sharesnapshot") String sharesnapshot, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-range") String range, @QueryParam("comp") String comp, Context context); - @PUT("{shareName}/{directory}/{fileName}") + @PUT("{shareName}/{filePath}") @ExpectedResponses({202}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono startCopy(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-meta-") Map metadata, @HeaderParam("x-ms-copy-source") String copySource, Context context); + Mono startCopy(@HostParam("url") String url, @PathParam("shareName") String shareName, @PathParam("filePath") String filePath, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-meta-") Map metadata, @HeaderParam("x-ms-copy-source") String copySource, Context context); - @PUT("{shareName}/{directory}/{fileName}") + @PUT("{shareName}/{filePath}") @ExpectedResponses({204}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono abortCopy(@HostParam("url") String url, @QueryParam("copyid") String copyId, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-copy-action") String copyActionAbortConstant, @HeaderParam("x-ms-version") String version, @QueryParam("comp") String comp, Context context); + Mono abortCopy(@HostParam("url") String url, @PathParam("shareName") String shareName, @PathParam("filePath") String filePath, @QueryParam("copyid") String copyId, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-copy-action") String copyActionAbortConstant, @HeaderParam("x-ms-version") String version, @QueryParam("comp") String comp, Context context); - @GET("{shareName}/{directory}/{fileName}") + @GET("{shareName}/{filePath}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono listHandles(@HostParam("url") String url, @QueryParam("marker") String marker, @QueryParam("maxresults") Integer maxresults, @QueryParam("timeout") Integer timeout, @QueryParam("sharesnapshot") String sharesnapshot, @HeaderParam("x-ms-version") String version, @QueryParam("comp") String comp, Context context); + Mono listHandles(@HostParam("url") String url, @PathParam("shareName") String shareName, @PathParam("filePath") String filePath, @QueryParam("marker") String marker, @QueryParam("maxresults") Integer maxresults, @QueryParam("timeout") Integer timeout, @QueryParam("sharesnapshot") String sharesnapshot, @HeaderParam("x-ms-version") String version, @QueryParam("comp") String comp, Context context); - @PUT("{shareName}/{directory}/{fileName}") + @PUT("{shareName}/{filePath}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono forceCloseHandles(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @QueryParam("marker") String marker, @QueryParam("sharesnapshot") String sharesnapshot, @HeaderParam("x-ms-handle-id") String handleId, @HeaderParam("x-ms-version") String version, @QueryParam("comp") String comp, Context context); + Mono forceCloseHandles(@HostParam("url") String url, @PathParam("shareName") String shareName, @PathParam("filePath") String filePath, @QueryParam("timeout") Integer timeout, @QueryParam("marker") String marker, @QueryParam("sharesnapshot") String sharesnapshot, @HeaderParam("x-ms-handle-id") String handleId, @HeaderParam("x-ms-version") String version, @QueryParam("comp") String comp, Context context); } /** * Creates a new file or replaces a file. Note it only initializes the file with no content. * + * @param shareName Name of the share. + * @param filePath Path to the file. * @param fileContentLength Specifies the maximum size for the file, up to 1 TB. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono createWithRestResponseAsync(long fileContentLength, Context context) { + public Mono createWithRestResponseAsync(String shareName, String filePath, long fileContentLength, Context context) { final Integer timeout = null; final String fileTypeConstant = "file"; final Map metadata = null; @@ -150,12 +154,14 @@ public Mono createWithRestResponseAsync(long fileContentLen final String fileCacheControl = null; final String fileContentDisposition = null; String fileContentMD5Converted = null; - return service.create(this.client.url(), timeout, this.client.version(), fileContentLength, fileTypeConstant, metadata, fileContentType, fileContentEncoding, fileContentLanguage, fileCacheControl, fileContentMD5Converted, fileContentDisposition, context); + return service.create(this.client.url(), shareName, filePath, timeout, this.client.version(), fileContentLength, fileTypeConstant, metadata, fileContentType, fileContentEncoding, fileContentLanguage, fileCacheControl, fileContentMD5Converted, fileContentDisposition, context); } /** * Creates a new file or replaces a file. Note it only initializes the file with no content. * + * @param shareName Name of the share. + * @param filePath Path to the file. * @param fileContentLength Specifies the maximum size for the file, up to 1 TB. * @param timeout The timeout parameter is expressed in seconds. For more information, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN">Setting Timeouts for File Service Operations.</a>. * @param metadata A name-value pair to associate with a file storage object. @@ -164,7 +170,7 @@ public Mono createWithRestResponseAsync(long fileContentLen * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono createWithRestResponseAsync(long fileContentLength, Integer timeout, Map metadata, FileHTTPHeaders fileHTTPHeaders, Context context) { + public Mono createWithRestResponseAsync(String shareName, String filePath, long fileContentLength, Integer timeout, Map metadata, FileHTTPHeaders fileHTTPHeaders, Context context) { final String fileTypeConstant = "file"; String fileContentType = null; if (fileHTTPHeaders != null) { @@ -191,26 +197,30 @@ public Mono createWithRestResponseAsync(long fileContentLen fileContentDisposition = fileHTTPHeaders.fileContentDisposition(); } String fileContentMD5Converted = Base64Util.encodeToString(fileContentMD5); - return service.create(this.client.url(), timeout, this.client.version(), fileContentLength, fileTypeConstant, metadata, fileContentType, fileContentEncoding, fileContentLanguage, fileCacheControl, fileContentMD5Converted, fileContentDisposition, context); + return service.create(this.client.url(), shareName, filePath, timeout, this.client.version(), fileContentLength, fileTypeConstant, metadata, fileContentType, fileContentEncoding, fileContentLanguage, fileCacheControl, fileContentMD5Converted, fileContentDisposition, context); } /** * Reads or downloads a file from the system, including its metadata and properties. * + * @param shareName Name of the share. + * @param filePath Path to the file. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono downloadWithRestResponseAsync(Context context) { + public Mono downloadWithRestResponseAsync(String shareName, String filePath, Context context) { final Integer timeout = null; final String range = null; final Boolean rangeGetContentMD5 = null; - return service.download(this.client.url(), timeout, this.client.version(), range, rangeGetContentMD5, context); + return service.download(this.client.url(), shareName, filePath, timeout, this.client.version(), range, rangeGetContentMD5, context); } /** * Reads or downloads a file from the system, including its metadata and properties. * + * @param shareName Name of the share. + * @param filePath Path to the file. * @param timeout The timeout parameter is expressed in seconds. For more information, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN">Setting Timeouts for File Service Operations.</a>. * @param range Return file data only from the specified byte range. * @param rangeGetContentMD5 When this header is set to true and specified together with the Range header, the service returns the MD5 hash for the range, as long as the range is less than or equal to 4 MB in size. @@ -218,68 +228,78 @@ public Mono downloadWithRestResponseAsync(Context context * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono downloadWithRestResponseAsync(Integer timeout, String range, Boolean rangeGetContentMD5, Context context) { - return service.download(this.client.url(), timeout, this.client.version(), range, rangeGetContentMD5, context); + public Mono downloadWithRestResponseAsync(String shareName, String filePath, Integer timeout, String range, Boolean rangeGetContentMD5, Context context) { + return service.download(this.client.url(), shareName, filePath, timeout, this.client.version(), range, rangeGetContentMD5, context); } /** * Returns all user-defined metadata, standard HTTP properties, and system properties for the file. It does not return the content of the file. * + * @param shareName Name of the share. + * @param filePath Path to the file. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono getPropertiesWithRestResponseAsync(Context context) { + public Mono getPropertiesWithRestResponseAsync(String shareName, String filePath, Context context) { final String sharesnapshot = null; final Integer timeout = null; - return service.getProperties(this.client.url(), sharesnapshot, timeout, this.client.version(), context); + return service.getProperties(this.client.url(), shareName, filePath, sharesnapshot, timeout, this.client.version(), context); } /** * Returns all user-defined metadata, standard HTTP properties, and system properties for the file. It does not return the content of the file. * + * @param shareName Name of the share. + * @param filePath Path to the file. * @param sharesnapshot The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. * @param timeout The timeout parameter is expressed in seconds. For more information, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN">Setting Timeouts for File Service Operations.</a>. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono getPropertiesWithRestResponseAsync(String sharesnapshot, Integer timeout, Context context) { - return service.getProperties(this.client.url(), sharesnapshot, timeout, this.client.version(), context); + public Mono getPropertiesWithRestResponseAsync(String shareName, String filePath, String sharesnapshot, Integer timeout, Context context) { + return service.getProperties(this.client.url(), shareName, filePath, sharesnapshot, timeout, this.client.version(), context); } /** * removes the file from the storage account. * + * @param shareName Name of the share. + * @param filePath Path to the file. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono deleteWithRestResponseAsync(Context context) { + public Mono deleteWithRestResponseAsync(String shareName, String filePath, Context context) { final Integer timeout = null; - return service.delete(this.client.url(), timeout, this.client.version(), context); + return service.delete(this.client.url(), shareName, filePath, timeout, this.client.version(), context); } /** * removes the file from the storage account. * + * @param shareName Name of the share. + * @param filePath Path to the file. * @param timeout The timeout parameter is expressed in seconds. For more information, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN">Setting Timeouts for File Service Operations.</a>. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono deleteWithRestResponseAsync(Integer timeout, Context context) { - return service.delete(this.client.url(), timeout, this.client.version(), context); + public Mono deleteWithRestResponseAsync(String shareName, String filePath, Integer timeout, Context context) { + return service.delete(this.client.url(), shareName, filePath, timeout, this.client.version(), context); } /** * Sets HTTP headers on the file. * + * @param shareName Name of the share. + * @param filePath Path to the file. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono setHTTPHeadersWithRestResponseAsync(Context context) { + public Mono setHTTPHeadersWithRestResponseAsync(String shareName, String filePath, Context context) { final Integer timeout = null; final Long fileContentLength = null; final String comp = "properties"; @@ -289,12 +309,14 @@ public Mono setHTTPHeadersWithRestResponseAsync(Con final String fileCacheControl = null; final String fileContentDisposition = null; String fileContentMD5Converted = null; - return service.setHTTPHeaders(this.client.url(), timeout, this.client.version(), fileContentLength, comp, fileContentType, fileContentEncoding, fileContentLanguage, fileCacheControl, fileContentMD5Converted, fileContentDisposition, context); + return service.setHTTPHeaders(this.client.url(), shareName, filePath, timeout, this.client.version(), fileContentLength, comp, fileContentType, fileContentEncoding, fileContentLanguage, fileCacheControl, fileContentMD5Converted, fileContentDisposition, context); } /** * Sets HTTP headers on the file. * + * @param shareName Name of the share. + * @param filePath Path to the file. * @param timeout The timeout parameter is expressed in seconds. For more information, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN">Setting Timeouts for File Service Operations.</a>. * @param fileContentLength 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. * @param fileHTTPHeaders Additional parameters for the operation. @@ -302,7 +324,7 @@ public Mono setHTTPHeadersWithRestResponseAsync(Con * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono setHTTPHeadersWithRestResponseAsync(Integer timeout, Long fileContentLength, FileHTTPHeaders fileHTTPHeaders, Context context) { + public Mono setHTTPHeadersWithRestResponseAsync(String shareName, String filePath, Integer timeout, Long fileContentLength, FileHTTPHeaders fileHTTPHeaders, Context context) { final String comp = "properties"; String fileContentType = null; if (fileHTTPHeaders != null) { @@ -329,40 +351,46 @@ public Mono setHTTPHeadersWithRestResponseAsync(Int fileContentDisposition = fileHTTPHeaders.fileContentDisposition(); } String fileContentMD5Converted = Base64Util.encodeToString(fileContentMD5); - return service.setHTTPHeaders(this.client.url(), timeout, this.client.version(), fileContentLength, comp, fileContentType, fileContentEncoding, fileContentLanguage, fileCacheControl, fileContentMD5Converted, fileContentDisposition, context); + return service.setHTTPHeaders(this.client.url(), shareName, filePath, timeout, this.client.version(), fileContentLength, comp, fileContentType, fileContentEncoding, fileContentLanguage, fileCacheControl, fileContentMD5Converted, fileContentDisposition, context); } /** * Updates user-defined metadata for the specified file. * + * @param shareName Name of the share. + * @param filePath Path to the file. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono setMetadataWithRestResponseAsync(Context context) { + public Mono setMetadataWithRestResponseAsync(String shareName, String filePath, Context context) { final Integer timeout = null; final Map metadata = null; final String comp = "metadata"; - return service.setMetadata(this.client.url(), timeout, metadata, this.client.version(), comp, context); + return service.setMetadata(this.client.url(), shareName, filePath, timeout, metadata, this.client.version(), comp, context); } /** * Updates user-defined metadata for the specified file. * + * @param shareName Name of the share. + * @param filePath Path to the file. * @param timeout The timeout parameter is expressed in seconds. For more information, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN">Setting Timeouts for File Service Operations.</a>. * @param metadata A name-value pair to associate with a file storage object. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono setMetadataWithRestResponseAsync(Integer timeout, Map metadata, Context context) { + public Mono setMetadataWithRestResponseAsync(String shareName, String filePath, Integer timeout, Map metadata, Context context) { final String comp = "metadata"; - return service.setMetadata(this.client.url(), timeout, metadata, this.client.version(), comp, context); + return service.setMetadata(this.client.url(), shareName, filePath, timeout, metadata, this.client.version(), comp, context); } /** * Upload a range of bytes to a file. * + * @param shareName Name of the share. + * @param filePath Path to the file. * @param range Specifies the range of bytes to be written. Both the start and end of the range must be specified. For an update operation, the range can be up to 4 MB in size. For a clear operation, the range can be up to the value of the file's full size. The File service accepts only a single byte range for the Range and 'x-ms-range' headers, and the byte range must be specified in the following format: bytes=startByte-endByte. * @param fileRangeWrite Specify one of the following options: - Update: Writes the bytes specified by the request body into the specified range. The Range and Content-Length headers must match to perform the update. - Clear: Clears the specified range and releases the space used in storage for that range. To clear a range, set the Content-Length header to zero, and set the Range header to a value that indicates the range to clear, up to maximum file size. Possible values include: 'update', 'clear'. * @param contentLength Specifies the number of bytes being transmitted in the request body. When the x-ms-write header is set to clear, the value of this header must be set to zero. @@ -370,17 +398,19 @@ public Mono setMetadataWithRestResponseAsync(Integer t * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono uploadRangeWithRestResponseAsync(String range, FileRangeWriteType fileRangeWrite, long contentLength, Context context) { + public Mono uploadRangeWithRestResponseAsync(String shareName, String filePath, String range, FileRangeWriteType fileRangeWrite, long contentLength, Context context) { final Flux optionalbody = null; final Integer timeout = null; final String comp = "range"; String contentMD5Converted = null; - return service.uploadRange(this.client.url(), optionalbody, timeout, range, fileRangeWrite, contentLength, contentMD5Converted, this.client.version(), comp, context); + return service.uploadRange(this.client.url(), shareName, filePath, optionalbody, timeout, range, fileRangeWrite, contentLength, contentMD5Converted, this.client.version(), comp, context); } /** * Upload a range of bytes to a file. * + * @param shareName Name of the share. + * @param filePath Path to the file. * @param range Specifies the range of bytes to be written. Both the start and end of the range must be specified. For an update operation, the range can be up to 4 MB in size. For a clear operation, the range can be up to the value of the file's full size. The File service accepts only a single byte range for the Range and 'x-ms-range' headers, and the byte range must be specified in the following format: bytes=startByte-endByte. * @param fileRangeWrite Specify one of the following options: - Update: Writes the bytes specified by the request body into the specified range. The Range and Content-Length headers must match to perform the update. - Clear: Clears the specified range and releases the space used in storage for that range. To clear a range, set the Content-Length header to zero, and set the Range header to a value that indicates the range to clear, up to maximum file size. Possible values include: 'update', 'clear'. * @param contentLength Specifies the number of bytes being transmitted in the request body. When the x-ms-write header is set to clear, the value of this header must be set to zero. @@ -391,30 +421,34 @@ public Mono uploadRangeWithRestResponseAsync(String ra * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono uploadRangeWithRestResponseAsync(String range, FileRangeWriteType fileRangeWrite, long contentLength, Flux optionalbody, Integer timeout, byte[] contentMD5, Context context) { + public Mono uploadRangeWithRestResponseAsync(String shareName, String filePath, String range, FileRangeWriteType fileRangeWrite, long contentLength, Flux optionalbody, Integer timeout, byte[] contentMD5, Context context) { final String comp = "range"; String contentMD5Converted = Base64Util.encodeToString(contentMD5); - return service.uploadRange(this.client.url(), optionalbody, timeout, range, fileRangeWrite, contentLength, contentMD5Converted, this.client.version(), comp, context); + return service.uploadRange(this.client.url(), shareName, filePath, optionalbody, timeout, range, fileRangeWrite, contentLength, contentMD5Converted, this.client.version(), comp, context); } /** * Returns the list of valid ranges for a file. * + * @param shareName Name of the share. + * @param filePath Path to the file. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono getRangeListWithRestResponseAsync(Context context) { + public Mono getRangeListWithRestResponseAsync(String shareName, String filePath, Context context) { final String sharesnapshot = null; final Integer timeout = null; final String range = null; final String comp = "rangelist"; - return service.getRangeList(this.client.url(), sharesnapshot, timeout, this.client.version(), range, comp, context); + return service.getRangeList(this.client.url(), shareName, filePath, sharesnapshot, timeout, this.client.version(), range, comp, context); } /** * Returns the list of valid ranges for a file. * + * @param shareName Name of the share. + * @param filePath Path to the file. * @param sharesnapshot The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. * @param timeout The timeout parameter is expressed in seconds. For more information, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN">Setting Timeouts for File Service Operations.</a>. * @param range Specifies the range of bytes over which to list ranges, inclusively. @@ -422,28 +456,32 @@ public Mono getRangeListWithRestResponseAsync(Context * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono getRangeListWithRestResponseAsync(String sharesnapshot, Integer timeout, String range, Context context) { + public Mono getRangeListWithRestResponseAsync(String shareName, String filePath, String sharesnapshot, Integer timeout, String range, Context context) { final String comp = "rangelist"; - return service.getRangeList(this.client.url(), sharesnapshot, timeout, this.client.version(), range, comp, context); + return service.getRangeList(this.client.url(), shareName, filePath, sharesnapshot, timeout, this.client.version(), range, comp, context); } /** * Copies a blob or file to a destination file within the storage account. * + * @param shareName Name of the share. + * @param filePath Path to the file. * @param copySource Specifies the URL of the source file or blob, up to 2 KB in length. To copy a file to another file within the same storage account, you may use Shared Key to authenticate the source file. If you are copying a file from another storage account, or if you are copying a blob from the same storage account or another storage account, then you must authenticate the source file or blob using a shared access signature. If the source is a public blob, no authentication is required to perform the copy operation. A file in a share snapshot can also be specified as a copy source. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono startCopyWithRestResponseAsync(String copySource, Context context) { + public Mono startCopyWithRestResponseAsync(String shareName, String filePath, String copySource, Context context) { final Integer timeout = null; final Map metadata = null; - return service.startCopy(this.client.url(), timeout, this.client.version(), metadata, copySource, context); + return service.startCopy(this.client.url(), shareName, filePath, timeout, this.client.version(), metadata, copySource, context); } /** * Copies a blob or file to a destination file within the storage account. * + * @param shareName Name of the share. + * @param filePath Path to the file. * @param copySource Specifies the URL of the source file or blob, up to 2 KB in length. To copy a file to another file within the same storage account, you may use Shared Key to authenticate the source file. If you are copying a file from another storage account, or if you are copying a blob from the same storage account or another storage account, then you must authenticate the source file or blob using a shared access signature. If the source is a public blob, no authentication is required to perform the copy operation. A file in a share snapshot can also be specified as a copy source. * @param timeout The timeout parameter is expressed in seconds. For more information, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN">Setting Timeouts for File Service Operations.</a>. * @param metadata A name-value pair to associate with a file storage object. @@ -451,59 +489,67 @@ public Mono startCopyWithRestResponseAsync(String copySo * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono startCopyWithRestResponseAsync(String copySource, Integer timeout, Map metadata, Context context) { - return service.startCopy(this.client.url(), timeout, this.client.version(), metadata, copySource, context); + public Mono startCopyWithRestResponseAsync(String shareName, String filePath, String copySource, Integer timeout, Map metadata, Context context) { + return service.startCopy(this.client.url(), shareName, filePath, timeout, this.client.version(), metadata, copySource, context); } /** * Aborts a pending Copy File operation, and leaves a destination file with zero length and full metadata. * + * @param shareName Name of the share. + * @param filePath Path to the file. * @param copyId The copy identifier provided in the x-ms-copy-id header of the original Copy File operation. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono abortCopyWithRestResponseAsync(String copyId, Context context) { + public Mono abortCopyWithRestResponseAsync(String shareName, String filePath, String copyId, Context context) { final Integer timeout = null; final String copyActionAbortConstant = "abort"; final String comp = "copy"; - return service.abortCopy(this.client.url(), copyId, timeout, copyActionAbortConstant, this.client.version(), comp, context); + return service.abortCopy(this.client.url(), shareName, filePath, copyId, timeout, copyActionAbortConstant, this.client.version(), comp, context); } /** * Aborts a pending Copy File operation, and leaves a destination file with zero length and full metadata. * + * @param shareName Name of the share. + * @param filePath Path to the file. * @param copyId The copy identifier provided in the x-ms-copy-id header of the original Copy File operation. * @param timeout The timeout parameter is expressed in seconds. For more information, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN">Setting Timeouts for File Service Operations.</a>. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono abortCopyWithRestResponseAsync(String copyId, Integer timeout, Context context) { + public Mono abortCopyWithRestResponseAsync(String shareName, String filePath, String copyId, Integer timeout, Context context) { final String copyActionAbortConstant = "abort"; final String comp = "copy"; - return service.abortCopy(this.client.url(), copyId, timeout, copyActionAbortConstant, this.client.version(), comp, context); + return service.abortCopy(this.client.url(), shareName, filePath, copyId, timeout, copyActionAbortConstant, this.client.version(), comp, context); } /** * Lists handles for file. * + * @param shareName Name of the share. + * @param filePath Path to the file. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono listHandlesWithRestResponseAsync(Context context) { + public Mono listHandlesWithRestResponseAsync(String shareName, String filePath, Context context) { final String marker = null; final Integer maxresults = null; final Integer timeout = null; final String sharesnapshot = null; final String comp = "listhandles"; - return service.listHandles(this.client.url(), marker, maxresults, timeout, sharesnapshot, this.client.version(), comp, context); + return service.listHandles(this.client.url(), shareName, filePath, marker, maxresults, timeout, sharesnapshot, this.client.version(), comp, context); } /** * Lists handles for file. * + * @param shareName Name of the share. + * @param filePath Path to the file. * @param marker A string value that identifies the portion of the list to be returned with the next list operation. The operation returns a marker value within the response body if the list returned was not complete. The marker value may then be used in a subsequent call to request the next set of list items. The marker value is opaque to the client. * @param maxresults Specifies the maximum number of entries to return. If the request does not specify maxresults, or specifies a value greater than 5,000, the server will return up to 5,000 items. * @param timeout The timeout parameter is expressed in seconds. For more information, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN">Setting Timeouts for File Service Operations.</a>. @@ -512,30 +558,34 @@ public Mono listHandlesWithRestResponseAsync(Context c * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono listHandlesWithRestResponseAsync(String marker, Integer maxresults, Integer timeout, String sharesnapshot, Context context) { + public Mono listHandlesWithRestResponseAsync(String shareName, String filePath, String marker, Integer maxresults, Integer timeout, String sharesnapshot, Context context) { final String comp = "listhandles"; - return service.listHandles(this.client.url(), marker, maxresults, timeout, sharesnapshot, this.client.version(), comp, context); + return service.listHandles(this.client.url(), shareName, filePath, marker, maxresults, timeout, sharesnapshot, this.client.version(), comp, context); } /** * Closes all handles open for given file. * + * @param shareName Name of the share. + * @param filePath Path to the file. * @param handleId Specifies handle ID opened on the file or directory to be closed. Asterix (‘*’) is a wildcard that specifies all handles. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono forceCloseHandlesWithRestResponseAsync(String handleId, Context context) { + public Mono forceCloseHandlesWithRestResponseAsync(String shareName, String filePath, String handleId, Context context) { final Integer timeout = null; final String marker = null; final String sharesnapshot = null; final String comp = "forceclosehandles"; - return service.forceCloseHandles(this.client.url(), timeout, marker, sharesnapshot, handleId, this.client.version(), comp, context); + return service.forceCloseHandles(this.client.url(), shareName, filePath, timeout, marker, sharesnapshot, handleId, this.client.version(), comp, context); } /** * Closes all handles open for given file. * + * @param shareName Name of the share. + * @param filePath Path to the file. * @param handleId Specifies handle ID opened on the file or directory to be closed. Asterix (‘*’) is a wildcard that specifies all handles. * @param timeout The timeout parameter is expressed in seconds. For more information, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN">Setting Timeouts for File Service Operations.</a>. * @param marker A string value that identifies the portion of the list to be returned with the next list operation. The operation returns a marker value within the response body if the list returned was not complete. The marker value may then be used in a subsequent call to request the next set of list items. The marker value is opaque to the client. @@ -544,8 +594,8 @@ public Mono forceCloseHandlesWithRestResponseAsy * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono forceCloseHandlesWithRestResponseAsync(String handleId, Integer timeout, String marker, String sharesnapshot, Context context) { + public Mono forceCloseHandlesWithRestResponseAsync(String shareName, String filePath, String handleId, Integer timeout, String marker, String sharesnapshot, Context context) { final String comp = "forceclosehandles"; - return service.forceCloseHandles(this.client.url(), timeout, marker, sharesnapshot, handleId, this.client.version(), comp, context); + return service.forceCloseHandles(this.client.url(), shareName, filePath, timeout, marker, sharesnapshot, handleId, this.client.version(), comp, context); } } diff --git a/storage/client/file/src/main/java/com/azure/storage/file/implementation/ServicesImpl.java b/storage/client/file/src/main/java/com/azure/storage/file/implementation/ServicesImpl.java index 5fcf68a794327..d2fc21cb7b595 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/implementation/ServicesImpl.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/implementation/ServicesImpl.java @@ -18,14 +18,15 @@ import com.azure.core.implementation.RestProxy; import com.azure.core.implementation.serializer.jackson.JacksonAdapter; import com.azure.core.util.Context; +import com.azure.storage.file.models.FileServiceProperties; import com.azure.storage.file.models.ListSharesIncludeType; import com.azure.storage.file.models.ServicesGetPropertiesResponse; import com.azure.storage.file.models.ServicesListSharesSegmentResponse; import com.azure.storage.file.models.ServicesSetPropertiesResponse; import com.azure.storage.file.models.StorageErrorException; -import com.azure.storage.file.models.StorageServiceProperties; import reactor.core.publisher.Mono; + import java.util.List; /** @@ -49,7 +50,7 @@ public final class ServicesImpl { * @param client the instance of the service client containing this operation class. */ public ServicesImpl(AzureFileStorageImpl client) { - this.service = RestProxy.create(ServicesService.class, client); + this.service = RestProxy.create(ServicesService.class, client.httpPipeline()); this.client = client; } @@ -58,12 +59,12 @@ public ServicesImpl(AzureFileStorageImpl client) { * proxy service to perform REST calls. */ @Host("{url}") - @Service("Storage Files Service") + @Service("Storage File Services") private interface ServicesService { @PUT("") @ExpectedResponses({202}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono setProperties(@HostParam("url") String url, @BodyParam("application/xml; charset=utf-8") StorageServiceProperties storageServiceProperties, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @QueryParam("restype") String restype, @QueryParam("comp") String comp, Context context); + Mono setProperties(@HostParam("url") String url, @BodyParam("application/xml; charset=utf-8") FileServiceProperties fileServiceProperties, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @QueryParam("restype") String restype, @QueryParam("comp") String comp, Context context); @GET("") @ExpectedResponses({200}) @@ -79,31 +80,31 @@ private interface ServicesService { /** * Sets properties for a storage account's File service endpoint, including properties for Storage Analytics metrics and CORS (Cross-Origin Resource Sharing) rules. * - * @param storageServiceProperties The StorageService properties. + * @param fileServiceProperties The FileService properties. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono setPropertiesWithRestResponseAsync(StorageServiceProperties storageServiceProperties, Context context) { + public Mono setPropertiesWithRestResponseAsync(FileServiceProperties fileServiceProperties, Context context) { final Integer timeout = null; final String restype = "service"; final String comp = "properties"; - return service.setProperties(this.client.url(), storageServiceProperties, timeout, this.client.version(), restype, comp, context); + return service.setProperties(this.client.url(), fileServiceProperties, timeout, this.client.version(), restype, comp, context); } /** * Sets properties for a storage account's File service endpoint, including properties for Storage Analytics metrics and CORS (Cross-Origin Resource Sharing) rules. * - * @param storageServiceProperties The StorageService properties. + * @param fileServiceProperties The FileService properties. * @param timeout The timeout parameter is expressed in seconds. For more information, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN">Setting Timeouts for File Service Operations.</a>. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono setPropertiesWithRestResponseAsync(StorageServiceProperties storageServiceProperties, Integer timeout, Context context) { + public Mono setPropertiesWithRestResponseAsync(FileServiceProperties fileServiceProperties, Integer timeout, Context context) { final String restype = "service"; final String comp = "properties"; - return service.setProperties(this.client.url(), storageServiceProperties, timeout, this.client.version(), restype, comp, context); + return service.setProperties(this.client.url(), fileServiceProperties, timeout, this.client.version(), restype, comp, context); } /** diff --git a/storage/client/file/src/main/java/com/azure/storage/file/implementation/SharesImpl.java b/storage/client/file/src/main/java/com/azure/storage/file/implementation/SharesImpl.java index bdc5fbadff999..befdb6335b90d 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/implementation/SharesImpl.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/implementation/SharesImpl.java @@ -12,6 +12,7 @@ import com.azure.core.annotations.Host; import com.azure.core.annotations.HostParam; import com.azure.core.annotations.PUT; +import com.azure.core.annotations.PathParam; import com.azure.core.annotations.QueryParam; import com.azure.core.annotations.Service; import com.azure.core.annotations.UnexpectedResponseExceptionType; @@ -29,9 +30,8 @@ import com.azure.storage.file.models.SharesSetQuotaResponse; import com.azure.storage.file.models.SignedIdentifier; import com.azure.storage.file.models.StorageErrorException; -import reactor.core.publisher.Mono; - import java.util.List; +import reactor.core.publisher.Mono; import java.util.Map; /** @@ -64,72 +64,74 @@ public SharesImpl(AzureFileStorageImpl client) { * proxy service to perform REST calls. */ @Host("{url}") - @Service("Storage Files Shares") + @Service("Storage File Shares") private interface SharesService { @PUT("{shareName}") @ExpectedResponses({201}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono create(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-meta-") Map metadata, @HeaderParam("x-ms-share-quota") Integer quota, @HeaderParam("x-ms-version") String version, @QueryParam("restype") String restype, Context context); + Mono create(@HostParam("url") String url, @PathParam ("shareName") String shareName, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-meta-") Map metadata, @HeaderParam("x-ms-share-quota") Integer quota, @HeaderParam("x-ms-version") String version, @QueryParam("restype") String restype, Context context); @GET("{shareName}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono getProperties(@HostParam("url") String url, @QueryParam("sharesnapshot") String sharesnapshot, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @QueryParam("restype") String restype, Context context); + Mono getProperties(@HostParam("url") String url, @PathParam ("shareName") String shareName, @QueryParam("sharesnapshot") String sharesnapshot, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @QueryParam("restype") String restype, Context context); @DELETE("{shareName}") @ExpectedResponses({202}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono delete(@HostParam("url") String url, @QueryParam("sharesnapshot") String sharesnapshot, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-delete-snapshots") DeleteSnapshotsOptionType deleteSnapshots, @QueryParam("restype") String restype, Context context); + Mono delete(@HostParam("url") String url, @PathParam ("shareName") String shareName, @QueryParam("sharesnapshot") String sharesnapshot, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-delete-snapshots") DeleteSnapshotsOptionType deleteSnapshots, @QueryParam("restype") String restype, Context context); @PUT("{shareName}") @ExpectedResponses({201}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono createSnapshot(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-meta-") Map metadata, @HeaderParam("x-ms-version") String version, @QueryParam("restype") String restype, @QueryParam("comp") String comp, Context context); + Mono createSnapshot(@HostParam("url") String url, @PathParam ("shareName") String shareName, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-meta-") Map metadata, @HeaderParam("x-ms-version") String version, @QueryParam("restype") String restype, @QueryParam("comp") String comp, Context context); @PUT("{shareName}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono setQuota(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-share-quota") Integer quota, @QueryParam("restype") String restype, @QueryParam("comp") String comp, Context context); + Mono setQuota(@HostParam("url") String url, @PathParam ("shareName") String shareName, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-share-quota") Integer quota, @QueryParam("restype") String restype, @QueryParam("comp") String comp, Context context); @PUT("{shareName}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono setMetadata(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-meta-") Map metadata, @HeaderParam("x-ms-version") String version, @QueryParam("restype") String restype, @QueryParam("comp") String comp, Context context); + Mono setMetadata(@HostParam("url") String url, @PathParam ("shareName") String shareName, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-meta-") Map metadata, @HeaderParam("x-ms-version") String version, @QueryParam("restype") String restype, @QueryParam("comp") String comp, Context context); @GET("{shareName}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono getAccessPolicy(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @QueryParam("restype") String restype, @QueryParam("comp") String comp, Context context); + Mono getAccessPolicy(@HostParam("url") String url, @PathParam ("shareName") String shareName, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @QueryParam("restype") String restype, @QueryParam("comp") String comp, Context context); @PUT("{shareName}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono setAccessPolicy(@HostParam("url") String url, @BodyParam("application/xml; charset=utf-8") SignedIdentifiersWrapper shareAcl, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @QueryParam("restype") String restype, @QueryParam("comp") String comp, Context context); + Mono setAccessPolicy(@HostParam("url") String url, @PathParam ("shareName") String shareName, @BodyParam("application/xml; charset=utf-8") SignedIdentifiersWrapper shareAcl, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @QueryParam("restype") String restype, @QueryParam("comp") String comp, Context context); @GET("{shareName}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono getStatistics(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @QueryParam("restype") String restype, @QueryParam("comp") String comp, Context context); + Mono getStatistics(@HostParam("url") String url, @PathParam ("shareName") String shareName, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @QueryParam("restype") String restype, @QueryParam("comp") String comp, Context context); } /** * Creates a new share under the specified account. If the share with the same name already exists, the operation fails. * + * @param shareName The name of the share to create. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono createWithRestResponseAsync(Context context) { + public Mono createWithRestResponseAsync(String shareName, Context context) { final Integer timeout = null; final Map metadata = null; final Integer quota = null; final String restype = "share"; - return service.create(this.client.url(), timeout, metadata, quota, this.client.version(), restype, context); + return service.create(this.client.url(), shareName, timeout, metadata, quota, this.client.version(), restype, context); } /** * Creates a new share under the specified account. If the share with the same name already exists, the operation fails. * + * @param shareName The name of the share to create. * @param timeout The timeout parameter is expressed in seconds. For more information, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN">Setting Timeouts for File Service Operations.</a>. * @param metadata A name-value pair to associate with a file storage object. * @param quota Specifies the maximum size of the share, in gigabytes. @@ -137,57 +139,61 @@ public Mono createWithRestResponseAsync(Context context) { * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono createWithRestResponseAsync(Integer timeout, Map metadata, Integer quota, Context context) { + public Mono createWithRestResponseAsync(String shareName, Integer timeout, Map metadata, Integer quota, Context context) { final String restype = "share"; - return service.create(this.client.url(), timeout, metadata, quota, this.client.version(), restype, context); + return service.create(this.client.url(), shareName, timeout, metadata, quota, this.client.version(), restype, context); } /** * Returns all user-defined metadata and system properties for the specified share or share snapshot. The data returned does not include the share's list of files. * + * @param shareName The name of the share that is having its properties retrieved. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono getPropertiesWithRestResponseAsync(Context context) { + public Mono getPropertiesWithRestResponseAsync(String shareName, Context context) { final String sharesnapshot = null; final Integer timeout = null; final String restype = "share"; - return service.getProperties(this.client.url(), sharesnapshot, timeout, this.client.version(), restype, context); + return service.getProperties(this.client.url(), shareName, sharesnapshot, timeout, this.client.version(), restype, context); } /** * Returns all user-defined metadata and system properties for the specified share or share snapshot. The data returned does not include the share's list of files. * + * @param shareName The name of the share that is having its properties retrieved. * @param sharesnapshot The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. * @param timeout The timeout parameter is expressed in seconds. For more information, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN">Setting Timeouts for File Service Operations.</a>. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono getPropertiesWithRestResponseAsync(String sharesnapshot, Integer timeout, Context context) { + public Mono getPropertiesWithRestResponseAsync(String shareName, String sharesnapshot, Integer timeout, Context context) { final String restype = "share"; - return service.getProperties(this.client.url(), sharesnapshot, timeout, this.client.version(), restype, context); + return service.getProperties(this.client.url(), shareName, sharesnapshot, timeout, this.client.version(), restype, context); } /** * Operation marks the specified share or share snapshot for deletion. The share or share snapshot and any files contained within it are later deleted during garbage collection. * + * @param shareName The name of the share to delete. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono deleteWithRestResponseAsync(Context context) { + public Mono deleteWithRestResponseAsync(String shareName, Context context) { final String sharesnapshot = null; final Integer timeout = null; final DeleteSnapshotsOptionType deleteSnapshots = null; final String restype = "share"; - return service.delete(this.client.url(), sharesnapshot, timeout, this.client.version(), deleteSnapshots, restype, context); + return service.delete(this.client.url(), shareName, sharesnapshot, timeout, this.client.version(), deleteSnapshots, restype, context); } /** * Operation marks the specified share or share snapshot for deletion. The share or share snapshot and any files contained within it are later deleted during garbage collection. * + * @param shareName The name of the share to delete. * @param sharesnapshot The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. * @param timeout The timeout parameter is expressed in seconds. For more information, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN">Setting Timeouts for File Service Operations.</a>. * @param deleteSnapshots Specifies the option include to delete the base share and all of its snapshots. Possible values include: 'include'. @@ -195,185 +201,197 @@ public Mono deleteWithRestResponseAsync(Context context) { * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono deleteWithRestResponseAsync(String sharesnapshot, Integer timeout, DeleteSnapshotsOptionType deleteSnapshots, Context context) { + public Mono deleteWithRestResponseAsync(String shareName, String sharesnapshot, Integer timeout, DeleteSnapshotsOptionType deleteSnapshots, Context context) { final String restype = "share"; - return service.delete(this.client.url(), sharesnapshot, timeout, this.client.version(), deleteSnapshots, restype, context); + return service.delete(this.client.url(), shareName, sharesnapshot, timeout, this.client.version(), deleteSnapshots, restype, context); } /** * Creates a read-only snapshot of a share. * + * @param shareName The name of the share that is having a snapshot created. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono createSnapshotWithRestResponseAsync(Context context) { + public Mono createSnapshotWithRestResponseAsync(String shareName, Context context) { final Integer timeout = null; final Map metadata = null; final String restype = "share"; final String comp = "snapshot"; - return service.createSnapshot(this.client.url(), timeout, metadata, this.client.version(), restype, comp, context); + return service.createSnapshot(this.client.url(), shareName, timeout, metadata, this.client.version(), restype, comp, context); } /** * Creates a read-only snapshot of a share. * + * @param shareName The name of the share that is having a snapshot created. * @param timeout The timeout parameter is expressed in seconds. For more information, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN">Setting Timeouts for File Service Operations.</a>. * @param metadata A name-value pair to associate with a file storage object. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono createSnapshotWithRestResponseAsync(Integer timeout, Map metadata, Context context) { + public Mono createSnapshotWithRestResponseAsync(String shareName, Integer timeout, Map metadata, Context context) { final String restype = "share"; final String comp = "snapshot"; - return service.createSnapshot(this.client.url(), timeout, metadata, this.client.version(), restype, comp, context); + return service.createSnapshot(this.client.url(), shareName, timeout, metadata, this.client.version(), restype, comp, context); } /** * Sets quota for the specified share. * + * @param shareName The name of the share that is having its quota set. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono setQuotaWithRestResponseAsync(Context context) { + public Mono setQuotaWithRestResponseAsync(String shareName, Context context) { final Integer timeout = null; final Integer quota = null; final String restype = "share"; final String comp = "properties"; - return service.setQuota(this.client.url(), timeout, this.client.version(), quota, restype, comp, context); + return service.setQuota(this.client.url(), shareName, timeout, this.client.version(), quota, restype, comp, context); } /** * Sets quota for the specified share. * + * @param shareName The name of the share that is having its quota set. * @param timeout The timeout parameter is expressed in seconds. For more information, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN">Setting Timeouts for File Service Operations.</a>. * @param quota Specifies the maximum size of the share, in gigabytes. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono setQuotaWithRestResponseAsync(Integer timeout, Integer quota, Context context) { + public Mono setQuotaWithRestResponseAsync(String shareName, Integer timeout, Integer quota, Context context) { final String restype = "share"; final String comp = "properties"; - return service.setQuota(this.client.url(), timeout, this.client.version(), quota, restype, comp, context); + return service.setQuota(this.client.url(), shareName, timeout, this.client.version(), quota, restype, comp, context); } /** * Sets one or more user-defined name-value pairs for the specified share. * + * @param shareName The name of the share having its metadata set. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono setMetadataWithRestResponseAsync(Context context) { + public Mono setMetadataWithRestResponseAsync(String shareName, Context context) { final Integer timeout = null; final Map metadata = null; final String restype = "share"; final String comp = "metadata"; - return service.setMetadata(this.client.url(), timeout, metadata, this.client.version(), restype, comp, context); + return service.setMetadata(this.client.url(), shareName, timeout, metadata, this.client.version(), restype, comp, context); } /** * Sets one or more user-defined name-value pairs for the specified share. * + * @param shareName The name of the share having its metadata set. * @param timeout The timeout parameter is expressed in seconds. For more information, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN">Setting Timeouts for File Service Operations.</a>. * @param metadata A name-value pair to associate with a file storage object. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono setMetadataWithRestResponseAsync(Integer timeout, Map metadata, Context context) { + public Mono setMetadataWithRestResponseAsync(String shareName, Integer timeout, Map metadata, Context context) { final String restype = "share"; final String comp = "metadata"; - return service.setMetadata(this.client.url(), timeout, metadata, this.client.version(), restype, comp, context); + return service.setMetadata(this.client.url(), shareName, timeout, metadata, this.client.version(), restype, comp, context); } /** * Returns information about stored access policies specified on the share. * + * @param shareName The name of the share having its access policy retrieved. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono getAccessPolicyWithRestResponseAsync(Context context) { + public Mono getAccessPolicyWithRestResponseAsync(String shareName, Context context) { final Integer timeout = null; final String restype = "share"; final String comp = "acl"; - return service.getAccessPolicy(this.client.url(), timeout, this.client.version(), restype, comp, context); + return service.getAccessPolicy(this.client.url(), shareName, timeout, this.client.version(), restype, comp, context); } /** * Returns information about stored access policies specified on the share. * + * @param shareName The name of the share having its access policy retrieved. * @param timeout The timeout parameter is expressed in seconds. For more information, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN">Setting Timeouts for File Service Operations.</a>. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono getAccessPolicyWithRestResponseAsync(Integer timeout, Context context) { + public Mono getAccessPolicyWithRestResponseAsync(String shareName, Integer timeout, Context context) { final String restype = "share"; final String comp = "acl"; - return service.getAccessPolicy(this.client.url(), timeout, this.client.version(), restype, comp, context); + return service.getAccessPolicy(this.client.url(), shareName, timeout, this.client.version(), restype, comp, context); } /** * Sets a stored access policy for use with shared access signatures. * + * @param shareName The name of the share having its access policy set. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono setAccessPolicyWithRestResponseAsync(Context context) { + public Mono setAccessPolicyWithRestResponseAsync(String shareName, Context context) { final Integer timeout = null; final String restype = "share"; final String comp = "acl"; SignedIdentifiersWrapper shareAclConverted = new SignedIdentifiersWrapper(null); - return service.setAccessPolicy(this.client.url(), shareAclConverted, timeout, this.client.version(), restype, comp, context); + return service.setAccessPolicy(this.client.url(), shareName, shareAclConverted, timeout, this.client.version(), restype, comp, context); } /** * Sets a stored access policy for use with shared access signatures. * + * @param shareName The name of the share having its access policy set. * @param shareAcl The ACL for the share. * @param timeout The timeout parameter is expressed in seconds. For more information, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN">Setting Timeouts for File Service Operations.</a>. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono setAccessPolicyWithRestResponseAsync(List shareAcl, Integer timeout, Context context) { + public Mono setAccessPolicyWithRestResponseAsync(String shareName, List shareAcl, Integer timeout, Context context) { final String restype = "share"; final String comp = "acl"; SignedIdentifiersWrapper shareAclConverted = new SignedIdentifiersWrapper(shareAcl); - return service.setAccessPolicy(this.client.url(), shareAclConverted, timeout, this.client.version(), restype, comp, context); + return service.setAccessPolicy(this.client.url(), shareName, shareAclConverted, timeout, this.client.version(), restype, comp, context); } /** * Retrieves statistics related to the share. * + * @param shareName The name of the share having its statistics retrieved. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono getStatisticsWithRestResponseAsync(Context context) { + public Mono getStatisticsWithRestResponseAsync(String shareName, Context context) { final Integer timeout = null; final String restype = "share"; final String comp = "stats"; - return service.getStatistics(this.client.url(), timeout, this.client.version(), restype, comp, context); + return service.getStatistics(this.client.url(), shareName, timeout, this.client.version(), restype, comp, context); } /** * Retrieves statistics related to the share. * + * @param shareName The name of the share having its statistics retrieved. * @param timeout The timeout parameter is expressed in seconds. For more information, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN">Setting Timeouts for File Service Operations.</a>. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono getStatisticsWithRestResponseAsync(Integer timeout, Context context) { + public Mono getStatisticsWithRestResponseAsync(String shareName, Integer timeout, Context context) { final String restype = "share"; final String comp = "stats"; - return service.getStatistics(this.client.url(), timeout, this.client.version(), restype, comp, context); + return service.getStatistics(this.client.url(), shareName, timeout, this.client.version(), restype, comp, context); } } diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/DeleteSnapshotsOptionType.java b/storage/client/file/src/main/java/com/azure/storage/file/models/DeleteSnapshotsOptionType.java index 080e8961a2710..002eb887ac448 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/DeleteSnapshotsOptionType.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/DeleteSnapshotsOptionType.java @@ -14,12 +14,7 @@ public enum DeleteSnapshotsOptionType { /** * Enum value include. */ - INCLUDE("include"), - - /** - * Enum value only. - */ - ONLY("only"); + INCLUDE("include"); /** * The actual serialized value for a DeleteSnapshotsOptionType instance. diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryInfo.java b/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryInfo.java index bd529f2538e2f..d651cbdb0e89a 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryInfo.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryInfo.java @@ -3,5 +3,37 @@ package com.azure.storage.file.models; +import java.time.OffsetDateTime; + +/** + * Contains information about a Directory in the storage File service. + */ public final class DirectoryInfo { + private final String eTag; + private final OffsetDateTime lastModified; + + /** + * Creates an instance of information about a specific Directory. + * + * @param eTag Entity tag that corresponds to the directory. + * @param lastModified Last time the directory was modified. + */ + public DirectoryInfo(final String eTag, final OffsetDateTime lastModified) { + this.eTag = eTag; + this.lastModified = lastModified; + } + + /** + * @return The entity tag that corresponds to the directory. + */ + public String eTag() { + return eTag; + } + + /** + * @return The last time the share was modified. + */ + public OffsetDateTime lastModified() { + return lastModified; + } } diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryProperties.java b/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryProperties.java index b140fd4a481eb..5ce45d09456b0 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryProperties.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryProperties.java @@ -3,5 +3,58 @@ package com.azure.storage.file.models; +import java.time.OffsetDateTime; +import java.util.Map; + +/** + * Contains properties information about a Directory in the storage File service. + */ public final class DirectoryProperties { + private final Map metadata; + private final String eTag; + private final OffsetDateTime lastModified; + private final boolean isServerEncrypted; + + /** + * Creates an instance of properties information about a specific Directory. + * + * @param metadata A set of name-value pairs that contain metadata for the directory. + * @param eTag Entity tag that corresponds to the directory. + * @param lastModified Last time the directory was modified. + * @param isServerEncrypted The value of this header is set to true if the directory metadata is completely encrypted using the specified algorithm. Otherwise, the value is set to false. + */ + public DirectoryProperties(final Map metadata, final String eTag, final OffsetDateTime lastModified, final boolean isServerEncrypted) { + this.metadata = metadata; + this.eTag = eTag; + this.lastModified = lastModified; + this.isServerEncrypted = isServerEncrypted; + } + + /** + * @return A set of name-value pairs that contain metadata for the directory. + */ + public Map metadata() { + return metadata; + } + + /** + * @return Entity tag that corresponds to the directory. + */ + public String eTag() { + return eTag; + } + + /** + * @return Entity tag that corresponds to the directory. + */ + public OffsetDateTime lastModified() { + return lastModified; + } + + /** + * @return The value of this header is true if the directory metadata is completely encrypted using the specified algorithm. Otherwise, the value is false. + */ + public boolean isServerEncrypted() { + return isServerEncrypted; + } } diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/DirectorySetMetadataInfo.java b/storage/client/file/src/main/java/com/azure/storage/file/models/DirectorySetMetadataInfo.java new file mode 100644 index 0000000000000..2e51fdbbd45aa --- /dev/null +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/DirectorySetMetadataInfo.java @@ -0,0 +1,34 @@ +package com.azure.storage.file.models; + +/** + * Contains metadata information about a Directory in the storage File service. + */ +public class DirectorySetMetadataInfo { + private final String eTag; + private final boolean isServerEncrypted; + + /** + * Creates an instance of information about a specific Directory. + * + * @param eTag Entity tag that corresponds to the share + * @param isServerEncrypted The value of this header is set to true if the directory metadata is completely encrypted using the specified algorithm. Otherwise, the value is set to false. + */ + public DirectorySetMetadataInfo(final String eTag, final boolean isServerEncrypted) { + this.eTag = eTag; + this.isServerEncrypted = isServerEncrypted; + } + + /** + * @return The entity tag that corresponds to the directory. + */ + public String eTag() { + return eTag; + } + + /** + * @return The value of this header is true if the directory metadata is completely encrypted using the specified algorithm. Otherwise, the value is false. + */ + public boolean isServerEncrypted() { + return isServerEncrypted; + } +} diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/FileCopyInfo.java b/storage/client/file/src/main/java/com/azure/storage/file/models/FileCopyInfo.java index fe4498b81c3da..f76a2096de9dd 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/FileCopyInfo.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/FileCopyInfo.java @@ -3,5 +3,63 @@ package com.azure.storage.file.models; +import java.time.OffsetDateTime; + +/** + * Contains copy information about a File in the storage File service. + */ public final class FileCopyInfo { + private final String eTag; + private final OffsetDateTime lastModified; + private final String copyId; + private final CopyStatusType copyStatus; + + /** + * Creates an instance of copy information about a specific File. + * + * @param eTag Entity tag that corresponds to the directory. + * @param lastModified Last time the directory was modified. + * @param copyId String identifier for this copy operation. + * @param copyStatus State of the copy operation with these values: + *
                    + *
                  • success: the copy completed successfully.
                  • + *
                  • pending: the copy is still in progress.
                  • + *
                  + */ + public FileCopyInfo(final String eTag, final OffsetDateTime lastModified, final String copyId, final CopyStatusType copyStatus) { + this.eTag = eTag; + this.lastModified = lastModified; + this.copyId = copyId; + this.copyStatus = copyStatus; + } + + /** + * @return Entity tag that corresponds to the directory. + */ + public String eTag() { + return eTag; + } + + /** + * @return Last time the directory was modified. + */ + public OffsetDateTime lastModified() { + return lastModified; + } + + /** + * @return String identifier for this copy operation. + */ + public String copyId() { + return copyId; + } + + /** + * @return State of the copy operation with these values: + * - success: the copy completed successfully. + * - pending: the copy is still in progress. + */ + public CopyStatusType copyStatus() { + return copyStatus; + } } diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/FileDownloadHeaders.java b/storage/client/file/src/main/java/com/azure/storage/file/models/FileDownloadHeaders.java index df05458677164..76e60103ac0b2 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/FileDownloadHeaders.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/FileDownloadHeaders.java @@ -6,6 +6,7 @@ import com.azure.core.annotations.HeaderCollection; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.util.ImplUtils; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -345,7 +346,7 @@ public FileDownloadHeaders eTag(String eTag) { * @return the contentMD5 value. */ public byte[] contentMD5() { - return Arrays.copyOf(this.contentMD5, this.contentMD5.length); + return ImplUtils.clone(this.contentMD5); } /** @@ -362,7 +363,7 @@ public byte[] contentMD5() { * @return the FileDownloadHeaders object itself. */ public FileDownloadHeaders contentMD5(byte[] contentMD5) { - this.contentMD5 = Arrays.copyOf(contentMD5, contentMD5.length); + this.contentMD5 = ImplUtils.clone(contentMD5); return this; } @@ -714,7 +715,7 @@ public FileDownloadHeaders copyStatus(CopyStatusType copyStatus) { * @return the fileContentMD5 value. */ public byte[] fileContentMD5() { - return Arrays.copyOf(this.fileContentMD5, this.fileContentMD5.length); + return ImplUtils.clone(this.fileContentMD5); } /** diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/FileDownloadInfo.java b/storage/client/file/src/main/java/com/azure/storage/file/models/FileDownloadInfo.java index 694fe762c8131..74ce72c7315e4 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/FileDownloadInfo.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/FileDownloadInfo.java @@ -3,5 +3,90 @@ package com.azure.storage.file.models; +import io.netty.buffer.ByteBuf; +import java.time.OffsetDateTime; +import java.util.Map; +import reactor.core.publisher.Flux; + +/** + * Contains download information about a File in the storage File service. + */ public final class FileDownloadInfo { + private final String eTag; + private final OffsetDateTime lastModified; + private final Map metadata; + private final Long contentLength; + private final String contentType; + private final String contentRange; + private final Flux body; + + /** + * Creates an instance of download information about a specific File. + * + * @param eTag Entity tag that corresponds to the directory. + * @param lastModified Last time the directory was modified. + * @param metadata A set of name-value pairs associated with this file as user-defined metadata. + * @param contentLength The number of bytes present in the response body. + * @param contentType The content type specified for the file. The default content type is application/octet-stream. + * @param contentRange Indicates the range of bytes returned if the client requested a subset of the file by setting the Range request header. + * @param body The download request body. + */ + public FileDownloadInfo(final String eTag, final OffsetDateTime lastModified, final Map metadata, final Long contentLength, final String contentType, final String contentRange, final Flux body) { + this.eTag = eTag; + this.lastModified = lastModified; + this.metadata = metadata; + this.contentLength = contentLength; + this.contentType = contentType; + this.contentRange = contentRange; + this.body = body; + } + + /** + * @return Entity tag that corresponds to the directory. + */ + public String eTag() { + return eTag; + } + + /** + * @return Last time the directory was modified. + */ + public OffsetDateTime lastModified() { + return lastModified; + } + + /** + * @return A set of name-value pairs associated with this file as user-defined metadata. + */ + public Map metadata() { + return metadata; + } + + /** + * @return The number of bytes present in the response body. + */ + public Long contentLength() { + return contentLength; + } + + /** + * @return The content type specified for the file. The default content type is application/octet-stream. + */ + public String contentType() { + return contentType; + } + + /** + * @return The range of bytes returned if the client requested a subset of the file by setting the Range request header. + */ + public String contentRange() { + return contentRange; + } + + /** + * @return The download request body. + */ + public Flux body() { + return body; + } } diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/FileGetPropertiesHeaders.java b/storage/client/file/src/main/java/com/azure/storage/file/models/FileGetPropertiesHeaders.java index ff397f6cd7ce1..727b476b60394 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/FileGetPropertiesHeaders.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/FileGetPropertiesHeaders.java @@ -6,6 +6,7 @@ import com.azure.core.annotations.HeaderCollection; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.util.ImplUtils; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -323,7 +324,7 @@ public FileGetPropertiesHeaders eTag(String eTag) { * @return the contentMD5 value. */ public byte[] contentMD5() { - return Arrays.copyOf(this.contentMD5, this.contentMD5.length); + return ImplUtils.clone(this.contentMD5); } /** @@ -335,7 +336,7 @@ public byte[] contentMD5() { * @return the FileGetPropertiesHeaders object itself. */ public FileGetPropertiesHeaders contentMD5(byte[] contentMD5) { - this.contentMD5 = Arrays.copyOf(contentMD5, contentMD5.length); + this.contentMD5 = ImplUtils.clone(contentMD5); return this; } diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/FileHTTPHeaders.java b/storage/client/file/src/main/java/com/azure/storage/file/models/FileHTTPHeaders.java index 01c69b3a9f299..7555663560b59 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/FileHTTPHeaders.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/FileHTTPHeaders.java @@ -4,6 +4,7 @@ package com.azure.storage.file.models; +import com.azure.core.implementation.util.ImplUtils; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.util.Arrays; @@ -146,7 +147,7 @@ public FileHTTPHeaders fileCacheControl(String fileCacheControl) { * @return the fileContentMD5 value. */ public byte[] fileContentMD5() { - return Arrays.copyOf(this.fileContentMD5, this.fileContentMD5.length); + return ImplUtils.clone(this.fileContentMD5); } /** @@ -156,7 +157,7 @@ public byte[] fileContentMD5() { * @return the FileHTTPHeaders object itself. */ public FileHTTPHeaders fileContentMD5(byte[] fileContentMD5) { - this.fileContentMD5 = Arrays.copyOf(fileContentMD5, fileContentMD5.length); + this.fileContentMD5 = ImplUtils.clone(fileContentMD5); return this; } diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/FileInfo.java b/storage/client/file/src/main/java/com/azure/storage/file/models/FileInfo.java index 47a634785e190..4f421f0b79348 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/FileInfo.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/FileInfo.java @@ -3,5 +3,47 @@ package com.azure.storage.file.models; +import java.time.OffsetDateTime; + +/** + * Contains information about a File in the storage File service. + */ public final class FileInfo { + private final String eTag; + private final OffsetDateTime lastModified; + private final Boolean isServerEncrypted; + + /** + * Creates an instance of information about a specific Directory. + * + * @param eTag Entity tag that corresponds to the directory. + * @param lastModified Last time the directory was modified. + * @param isServerEncrypted The value of this header is set to true if the directory metadata is completely encrypted using the specified algorithm. Otherwise, the value is set to false. + */ + public FileInfo(final String eTag, final OffsetDateTime lastModified, final Boolean isServerEncrypted) { + this.eTag = eTag; + this.lastModified = lastModified; + this.isServerEncrypted = isServerEncrypted; + } + + /** + * @return The entity tag that corresponds to the directory. + */ + public String eTag() { + return eTag; + } + + /** + * @return The last time the share was modified. + */ + public OffsetDateTime lastModified() { + return lastModified; + } + + /** + * @return The value of this header is true if the directory metadata is completely encrypted using the specified algorithm. Otherwise, the value is false. + */ + public Boolean isServerEncrypted() { + return isServerEncrypted; + } } diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/FileMetadataInfo.java b/storage/client/file/src/main/java/com/azure/storage/file/models/FileMetadataInfo.java new file mode 100644 index 0000000000000..29b222b480758 --- /dev/null +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/FileMetadataInfo.java @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.storage.file.models; + +public class FileMetadataInfo { + private final String eTag; + private final Boolean isServerEncrypted; + + public FileMetadataInfo(final String eTag, final Boolean isServerEncrypted) { + this.eTag = eTag; + this.isServerEncrypted = isServerEncrypted; + } + + public String eTag() { + return eTag; + } + + public Boolean isServerEncrypted() { + return isServerEncrypted; + } +} diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/FileProperties.java b/storage/client/file/src/main/java/com/azure/storage/file/models/FileProperties.java index dd691c0b06871..670057a600b7b 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/FileProperties.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/FileProperties.java @@ -3,5 +3,200 @@ package com.azure.storage.file.models; +import com.azure.core.implementation.util.ImplUtils; +import java.time.OffsetDateTime; +import java.util.Map; + +/** + * Contains property information about a File in the storage File service. + */ public final class FileProperties { + private final String eTag; + private final OffsetDateTime lastModified; + private final Map metadata; + private final String fileType; + private final Long contentLength; + private final String contentType; + private final byte[] contentMD5; + private final String contentEncoding; + private final String cacheControl; + private final String contentDisposition; + private final OffsetDateTime copyCompletionTime; + private final String copyStatusDescription; + private final String copyId; + private final String copyProgress; + private final String copySource; + private final CopyStatusType copyStatus; + private final Boolean isServerEncrypted; + + /** + * Creates an instance of property information about a specific File. + * + * @param eTag Entity tag that corresponds to the directory. + * @param lastModified Last time the directory was modified. + * @param metadata A set of name-value pairs associated with this file as user-defined metadata. + * @param fileType Type of the file. + * @param contentLength The number of bytes present in the response body. + * @param contentType The content type specified for the file. The default content type is application/octet-stream. + * @param contentMD5 The MD5 hash of the file to check the message content integrity. + * @param contentEncoding This header returns the value that was specified for the Content-Encoding request header. + * @param cacheControl This header is returned if it was previously specified for the file. + * @param contentDisposition The value that was specified for the x-ms-content-disposition header and specifies how to process the response. + * @param copyCompletionTime Conclusion time of the last attempted Copy File operation where this file was the destination file. + * @param copyStatusDescription Appears when x-ms-copy-status is failed or pending. Describes cause of fatal or non-fatal copy operation failure. + * @param copyId String identifier for the last attempted Copy File operation where this file was the destination file. + * @param copyProgress Contains the number of bytes copied and the total bytes in the source in the last attempted Copy File operation where this file was the destination file. + * @param copySource URL up to 2KB in length that specifies the source file used in the last attempted Copy File operation where this file was the destination file. + * @param copyStatus State of the copy operation identified by x-ms-copy-id, with these values: + * - success: Copy completed successfully. + * - pending: Copy is in progress. Check x-ms-copy-status-description if intermittent, non-fatal errors impede copy progress but don't cause failure. + * - aborted: Copy was ended by Abort Copy File. + * - failed: Copy failed. See x-ms-copy-status-description for failure details. + * @param isServerEncrypted The value of this header is set to true if the file data and application metadata are completely encrypted using the specified algorithm. Otherwise, the value is set to false. + */ + public FileProperties(final String eTag, final OffsetDateTime lastModified, final Map metadata, + final String fileType, final Long contentLength, final String contentType, final byte[] contentMD5, + final String contentEncoding, final String cacheControl, final String contentDisposition, + final OffsetDateTime copyCompletionTime, final String copyStatusDescription, final String copyId, + final String copyProgress, final String copySource, final CopyStatusType copyStatus, final Boolean isServerEncrypted) { + this.eTag = eTag; + this.lastModified = lastModified; + this.metadata = metadata; + this.fileType = fileType; + this.contentLength = contentLength; + this.contentType = contentType; + this.contentMD5 = ImplUtils.clone(contentMD5); + this.contentEncoding = contentEncoding; + this.cacheControl = cacheControl; + this.contentDisposition = contentDisposition; + this.copyCompletionTime = copyCompletionTime; + this.copyStatusDescription = copyStatusDescription; + this.copyId = copyId; + this.copyProgress = copyProgress; + this.copySource = copySource; + this.copyStatus = copyStatus; + this.isServerEncrypted = isServerEncrypted; + } + + /** + * @return Entity tag that corresponds to the directory. + */ + public String eTag() { + return eTag; + } + + /** + * @return Last time the directory was modified. + */ + public OffsetDateTime lastModified() { + return lastModified; + } + + /** + * @return A set of name-value pairs associated with this file as user-defined metadata. + */ + public Map metadata() { + return metadata; + } + + /** + * @return The number of bytes present in the response body. + */ + public Long contentLength() { + return contentLength; + } + + /** + * @return The type of the file. + */ + public String fileType() { + return fileType; + } + /** + * @return The content type specified for the file. The default content type is application/octet-stream. + */ + public String contentType() { + return contentType; + } + + /** + * @return The MD5 hash of the file. + */ + public byte[] contentMD5() { + return ImplUtils.clone(contentMD5); + } + + /** + * @return The value that was specified for the Content-Encoding request header. + */ + public String contentEncoding() { + return contentEncoding; + } + + /** + * @return This header is returned if it was previously specified for the file. + */ + public String cacheControl() { + return cacheControl; + } + + /** + * @return The value that was specified for the x-ms-content-disposition header and specifies how to process the response. + */ + public String contentDisposition() { + return contentDisposition; + } + + /** + * @return Conclusion time of the last attempted Copy File operation where this file was the destination file. + */ + public OffsetDateTime copyCompletionTime() { + return copyCompletionTime; + } + + /** + * @return When x-ms-copy-status is failed or pending. Describes cause of fatal or non-fatal copy operation failure. + */ + public String copyStatusDescription() { + return copyStatusDescription; + } + + /** + * @return String identifier for the last attempted Copy File operation where this file was the destination file. + */ + public String copyId() { + return copyId; + } + + /** + * @return The number of bytes copied and the total bytes in the source in the last attempted Copy File operation where this file was the destination file. + */ + public String copyProgress() { + return copyProgress; + } + + /** + * @return URL up to 2KB in length that specifies the source file used in the last attempted Copy File operation where this file was the destination file. + */ + public String copySource() { + return copySource; + } + + /** + * @return State of the copy operation identified by x-ms-copy-id, with these values: + * - success: Copy completed successfully. + * - pending: Copy is in progress. Check x-ms-copy-status-description if intermittent, non-fatal errors impede copy progress but don't cause failure. + * - aborted: Copy was ended by Abort Copy File. + * - failed: Copy failed. See x-ms-copy-status-description for failure details. + */ + public CopyStatusType copyStatus() { + return copyStatus; + } + + /** + * @return True if the file data and application metadata are completely encrypted using the specified algorithm. Otherwise, return false. + */ + public Boolean isServerEncrypted() { + return isServerEncrypted; + } } diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/FileRange.java b/storage/client/file/src/main/java/com/azure/storage/file/models/FileRange.java new file mode 100644 index 0000000000000..9c264f3f4f8fd --- /dev/null +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/FileRange.java @@ -0,0 +1,47 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.storage.file.models; + +import java.util.Objects; + +/** + * The range of a file in the storage file service. + */ +public final class FileRange { + private final long start; + private final Long end; + + /** + * Create an instance of the range of a file. Both the start and end of the range must be specified. + * @param start Specifies the start of bytes to be written. + * @param end Specifies the end of bytes to be written + */ + public FileRange(final long start, final Long end) { + this.start = start; + this.end = end; + } + + /** + * @return The start of bytes to be written. + */ + public long start() { + return start; + } + + /** + * @return The end of bytes to be written. + */ + public Long end() { + return end; + } + + /** + * @return The string format of the FileRange written into request. + */ + @Override + public String toString() { + String endString = Objects.toString(end); + return "bytes=" + String.valueOf(start) + "-" + endString; + } +} diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/FileRef.java b/storage/client/file/src/main/java/com/azure/storage/file/models/FileRef.java index 0cd1261d2af97..8ed977bee61c9 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/FileRef.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/FileRef.java @@ -3,5 +3,47 @@ package com.azure.storage.file.models; +/** + * Contains file or directory reference information in the storage File service. + */ public final class FileRef { + private final String name; + private final boolean isDirectory; + private final FileProperty fileProperty; + + /** + * Creates an instance of file or directory reference information about a specific Share. + * + * @param name Name of the file or the directory. + * @param isDirectory A boolean set to true if the reference is a directory, false if the reference is a file. + * @param fileProperty Property of a file. Pass {@code null} if the reference is a directory. + */ + public FileRef(final String name, final boolean isDirectory, final FileProperty fileProperty) { + this.name = name; + this.isDirectory = isDirectory; + this.fileProperty = fileProperty; + } + + + /** + * @return Name of the file or the directory. + */ + public String name() { + return name; + } + + /** + * @return True if the reference is a directory, or false if the reference is a file. + */ + public boolean isDirectory() { + return isDirectory; + } + + /** + * @return Property of a file. Return {@code null} if the reference is a directory. + */ + public FileProperty fileProperties() { + return fileProperty; + } + } diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/FileServiceProperties.java b/storage/client/file/src/main/java/com/azure/storage/file/models/FileServiceProperties.java index 8ad66286adba1..ef42bbb4becf8 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/FileServiceProperties.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/FileServiceProperties.java @@ -1,7 +1,115 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +// Code generated by Microsoft (R) AutoRest Code Generator. package com.azure.storage.file.models; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; +import java.util.ArrayList; +import java.util.List; + +/** + * Storage service properties. + */ +@JacksonXmlRootElement(localName = "StorageServiceProperties") public final class FileServiceProperties { + /* + * A summary of request statistics grouped by API in hourly aggregates for + * files. + */ + @JsonProperty(value = "HourMetrics") + private Metrics hourMetrics; + + /* + * A summary of request statistics grouped by API in minute aggregates for + * files. + */ + @JsonProperty(value = "MinuteMetrics") + private Metrics minuteMetrics; + + private static final class CorsWrapper { + @JacksonXmlProperty(localName = "CorsRule") + private final List items; + + @JsonCreator + private CorsWrapper(@JacksonXmlProperty(localName = "CorsRule") List items) { + this.items = items; + } + } + + /* + * The set of CORS rules. + */ + @JsonProperty(value = "Cors") + private CorsWrapper cors; + + /** + * Get the hourMetrics property: A summary of request statistics grouped by + * API in hourly aggregates for files. + * + * @return the hourMetrics value. + */ + public Metrics hourMetrics() { + return this.hourMetrics; + } + + /** + * Set the hourMetrics property: A summary of request statistics grouped by + * API in hourly aggregates for files. + * + * @param hourMetrics the hourMetrics value to set. + * @return the FileServiceProperties object itself. + */ + public FileServiceProperties hourMetrics(Metrics hourMetrics) { + this.hourMetrics = hourMetrics; + return this; + } + + /** + * Get the minuteMetrics property: A summary of request statistics grouped + * by API in minute aggregates for files. + * + * @return the minuteMetrics value. + */ + public Metrics minuteMetrics() { + return this.minuteMetrics; + } + + /** + * Set the minuteMetrics property: A summary of request statistics grouped + * by API in minute aggregates for files. + * + * @param minuteMetrics the minuteMetrics value to set. + * @return the FileServiceProperties object itself. + */ + public FileServiceProperties minuteMetrics(Metrics minuteMetrics) { + this.minuteMetrics = minuteMetrics; + return this; + } + + /** + * Get the cors property: The set of CORS rules. + * + * @return the cors value. + */ + public List cors() { + if (this.cors == null) { + this.cors = new CorsWrapper(new ArrayList()); + } + return this.cors.items; + } + + /** + * Set the cors property: The set of CORS rules. + * + * @param cors the cors value to set. + * @return the FileServiceProperties object itself. + */ + public FileServiceProperties cors(List cors) { + this.cors = new CorsWrapper(cors); + return this; + } } diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/FileUploadInfo.java b/storage/client/file/src/main/java/com/azure/storage/file/models/FileUploadInfo.java index 644075f434f74..26ffc82c314bd 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/FileUploadInfo.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/FileUploadInfo.java @@ -3,5 +3,35 @@ package com.azure.storage.file.models; +import com.azure.core.implementation.util.ImplUtils; +import java.time.OffsetDateTime; + public final class FileUploadInfo { + private String eTag; + private OffsetDateTime lastModified; + private byte[] contentMD5; + private Boolean isServerEncrypted; + + public FileUploadInfo(final String eTag, final OffsetDateTime lastModified, final byte[] contentMD5, final Boolean isServerEncrypted) { + this.eTag = eTag; + this.lastModified = lastModified; + this.contentMD5 = ImplUtils.clone(contentMD5); + this.isServerEncrypted = isServerEncrypted; + } + + public String eTag() { + return eTag; + } + + public OffsetDateTime lastModified() { + return lastModified; + } + + public byte[] contentMD5() { + return ImplUtils.clone(contentMD5); + } + + public Boolean isServerEncrypted() { + return isServerEncrypted; + } } diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/FileUploadRangeHeaders.java b/storage/client/file/src/main/java/com/azure/storage/file/models/FileUploadRangeHeaders.java index 686014ab74e59..68b8ed554de37 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/FileUploadRangeHeaders.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/FileUploadRangeHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.file.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.util.ImplUtils; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -138,7 +139,7 @@ public FileUploadRangeHeaders lastModified(OffsetDateTime lastModified) { * @return the contentMD5 value. */ public byte[] contentMD5() { - return Arrays.copyOf(this.contentMD5, this.contentMD5.length); + return ImplUtils.clone(this.contentMD5); } /** @@ -151,7 +152,7 @@ public byte[] contentMD5() { * @return the FileUploadRangeHeaders object itself. */ public FileUploadRangeHeaders contentMD5(byte[] contentMD5) { - this.contentMD5 = Arrays.copyOf(contentMD5, contentMD5.length); + this.contentMD5 = ImplUtils.clone(contentMD5); return this; } diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/ListFilesAndDirectoriesSegmentResponse.java b/storage/client/file/src/main/java/com/azure/storage/file/models/ListFilesAndDirectoriesSegmentResponse.java index 1ba129b882372..19f443c9ba0f7 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/ListFilesAndDirectoriesSegmentResponse.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/ListFilesAndDirectoriesSegmentResponse.java @@ -26,7 +26,7 @@ public final class ListFilesAndDirectoriesSegmentResponse { private String shareName; /* - * The shareSnapshot property. + * The snapshot property. */ @JacksonXmlProperty(localName = "ShareSnapshot", isAttribute = true) private String shareSnapshot; @@ -108,18 +108,18 @@ public ListFilesAndDirectoriesSegmentResponse shareName(String shareName) { } /** - * Get the shareSnapshot property: The shareSnapshot property. + * Get the snapshot property: The snapshot property. * - * @return the shareSnapshot value. + * @return the snapshot value. */ public String shareSnapshot() { return this.shareSnapshot; } /** - * Set the shareSnapshot property: The shareSnapshot property. + * Set the snapshot property: The snapshot property. * - * @param shareSnapshot the shareSnapshot value to set. + * @param shareSnapshot the snapshot value to set. * @return the ListFilesAndDirectoriesSegmentResponse object itself. */ public ListFilesAndDirectoriesSegmentResponse shareSnapshot(String shareSnapshot) { diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/ListSharesOptions.java b/storage/client/file/src/main/java/com/azure/storage/file/models/ListSharesOptions.java index 612b95238ea2a..a75b4bab697f1 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/ListSharesOptions.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/ListSharesOptions.java @@ -3,5 +3,107 @@ package com.azure.storage.file.models; +/** + * A set of options for selecting shares from Storage File service. + * + *
                    + *
                  • + * Providing {@link ListSharesOptions#prefix(String) prefix} will filter selections to {@link ShareItem shares} + * that that begin with the prefix. + *
                  • + *
                  • + * Providing {@link ListSharesOptions#maxResults(Integer) maxResults} will limit the number of {@link ShareItem shares} + * returned in a single page. + *
                  • + *
                  • + * Setting {@link ListSharesOptions#includeMetadata(boolean) includeMetadata} to true will include the metadata + * of each {@link ShareItem share}, if false {@link ShareItem#metadata() metadata} for each share will be {@code null}. + *
                  • + *
                  • + * Setting {@link ListSharesOptions#includeSnapshots(boolean) includeSnapshots} to true will include snapshots + * of each {@link ShareItem share}, the snapshot will be included as separate items in the response and will be + * identifiable by {@link ShareItem#snapshot() snapshot} having a value. The base share will contain {@code null} + * for the snapshot. + *
                  • + *
                  + */ public final class ListSharesOptions { + private String prefix; + private Integer maxResults; + private boolean includeMetadata; + private boolean includeSnapshots; + + /** + * Sets the prefix that a share must match to be included in the listing. + * + * @param prefix The prefix that shares must start with to pass the filter + * @return An updated ListSharesOptions object + */ + public ListSharesOptions prefix(String prefix) { + this.prefix = prefix; + return this; + } + + /** + * @return the prefix that a share must match to be included in the listing + */ + public String prefix() { + return prefix; + } + + /** + * Sets the maximum number of shares to include in a single response. + * + * @param maxResults Maximum number of shares to include in a single response. This value must be between 1 and 5000. + * @return An updated ListSharesOptions object + */ + public ListSharesOptions maxResults(Integer maxResults) { + this.maxResults = maxResults; + return this; + } + + /** + * @return the maximum number of shares to inlcude in a single response + */ + public Integer maxResults() { + return maxResults; + } + + /** + * Sets the status of including share metadata when listing shares + * + * If listing snapshots as well this will also determine if the snapshots have their metadata included as well. + * + * @param includeMetadata Flag indicating if metadata should be including in the listing + * @return An updated ListSharesOptions object + */ + public ListSharesOptions includeMetadata(boolean includeMetadata) { + this.includeMetadata = includeMetadata; + return this; + } + + /** + * @return the status of include share metadata when listing shares + */ + public boolean includeMetadata() { + return includeMetadata; + } + + /** + * Sets the status of including share snapshots when listing shares + * + * @param includeSnapshots Flag indicating if snapshots should be included in the listing + * @return An updated ListSharesOptions object + */ + public ListSharesOptions includeSnapshots(boolean includeSnapshots) { + this.includeSnapshots = includeSnapshots; + return this; + } + + /** + * @return the status of including share snapshots when listing shares + */ + public boolean includeSnapshots() { + return includeSnapshots; + } } diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/ServicesGetPropertiesResponse.java b/storage/client/file/src/main/java/com/azure/storage/file/models/ServicesGetPropertiesResponse.java index 267a198ab8b8d..92a15ab7d889e 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/ServicesGetPropertiesResponse.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/ServicesGetPropertiesResponse.java @@ -11,7 +11,7 @@ /** * Contains all response data for the getProperties operation. */ -public final class ServicesGetPropertiesResponse extends ResponseBase { +public final class ServicesGetPropertiesResponse extends ResponseBase { /** * Creates an instance of ServicesGetPropertiesResponse. * @@ -21,7 +21,7 @@ public final class ServicesGetPropertiesResponse extends ResponseBase metadata; + /** * Get the lastModified property: The lastModified property. * @@ -98,4 +104,13 @@ public ShareProperties quota(int quota) { this.quota = quota; return this; } + + public Map metadata() { + return metadata; + } + + public ShareProperties metadata(Map metadata) { + this.metadata = metadata; + return this; + } } diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/ShareSnapshotInfo.java b/storage/client/file/src/main/java/com/azure/storage/file/models/ShareSnapshotInfo.java index 2a3e17d8ad01d..4e95b45182a23 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/ShareSnapshotInfo.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/ShareSnapshotInfo.java @@ -3,5 +3,49 @@ package com.azure.storage.file.models; -public final class ShareSnapshotInfo { +import java.time.OffsetDateTime; + +/** + * Contains information about a snapshot of a Share in the storage File service. + */ +public final class ShareSnapshotInfo { + private String snapshot; + private String eTag; + private OffsetDateTime lastModified; + + /** + * Creates an instance of snapshot information for a specific Share. + * + * @param snapshot Identifier for the snapshot + * @param eTag Entity tag that corresponds to the snapshot + * @param lastModified Last time the Share was modified if the snapshot was created without metadata, if the snapshot + * was created with metadata then it will be the time the snapshot was created + */ + public ShareSnapshotInfo(String snapshot, String eTag, OffsetDateTime lastModified) { + this.snapshot = snapshot; + this.eTag = eTag; + this.lastModified = lastModified; + } + + /** + * @return the identifier of the snapshot + */ + public String snapshot() { + return snapshot; + } + + /** + * @return the entity tag that corresponds to the snapshot + */ + public String eTag() { + return eTag; + } + + /** + * @return the last time the share was modified if the snapshot was created without metadata, otherwise this is the + * time that the snapshot was created. + */ + public OffsetDateTime lastModified() { + return lastModified; + } } diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/ShareStatistics.java b/storage/client/file/src/main/java/com/azure/storage/file/models/ShareStatistics.java index aef819551c53f..d10648dfb3dc8 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/ShareStatistics.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/ShareStatistics.java @@ -3,5 +3,25 @@ package com.azure.storage.file.models; +/** + * Contains statistics about a Share in the storage File service. + */ public final class ShareStatistics { + private final int shareUsageInGB; + + /** + * Creates an instance of storage statistics for a Share. + * + * @param shareUsageInGB Size in GB of the Share + */ + public ShareStatistics(int shareUsageInGB) { + this.shareUsageInGB = shareUsageInGB; + } + + /** + * @return the size in GB of the Share + */ + public int getShareUsageInGB() { + return shareUsageInGB; + } } diff --git a/storage/client/file/src/samples/java/com/azure/file/AsyncSample.java b/storage/client/file/src/samples/java/com/azure/file/AsyncSample.java new file mode 100644 index 0000000000000..12a0ae4e36c88 --- /dev/null +++ b/storage/client/file/src/samples/java/com/azure/file/AsyncSample.java @@ -0,0 +1,67 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.file; + +import com.azure.core.util.configuration.ConfigurationManager; +import com.azure.storage.file.FileServiceAsyncClient; +import com.azure.storage.file.FileServiceClientBuilder; +import java.util.UUID; + +/** + * Sample demonstrates how to create, list and delete a share using the async file service client. + */ +public class AsyncSample { + private static final String ENDPOINT = ConfigurationManager.getConfiguration().get("AZURE_STORAGE_FILE_ENDPOINT"); + + // This is the helper method to generate random name. + private static String generateRandomName() { + return UUID.randomUUID().toString().substring(0, 8); + } + + /** + * The main method show how to make async cal for creating and listing shares. + * @param args No args needed for the main method + */ + public static void main(String[] args) { + // Create a file service client + FileServiceAsyncClient fileServiceAsyncClient = new FileServiceClientBuilder().endpoint(ENDPOINT) + .buildAsyncClient(); + // Create a share + String shareName = generateRandomName(); + fileServiceAsyncClient.createShare(shareName).subscribe( + response -> { + System.out.printf("Successfully created a share with status code: %d.", response.statusCode()); + }, + err -> { + System.out.println("Failed to create a share. Reasons: " + err.getMessage()); + }, + () -> { + System.out.println("Completed creating a share!"); + } + ); + + // List all shares and delete them. + fileServiceAsyncClient.listShares().subscribe( + shareItem -> { + System.out.println("There is a share named: " + shareItem.name()); + fileServiceAsyncClient.deleteShare(shareItem.name()).subscribe( + response -> { + System.out.printf("Successfully delete the share: %s.", shareItem.name()); + }, + err -> { + System.out.printf("Failed to delete the share: %s. Reasons: %s.", shareItem.name(), err.getMessage()); + }, + () -> { + System.out.println("Completed deleting the share."); + } + ); + }, + err -> { + System.out.println("Failed to list shares. Reasons: " + err.getMessage()); + }, + () -> { + System.out.println("Completed the listing and deleting the shares."); + } + ); + } +} diff --git a/storage/client/file/src/samples/java/com/azure/file/DirectorySample.java b/storage/client/file/src/samples/java/com/azure/file/DirectorySample.java new file mode 100644 index 0000000000000..0c3e7d768082d --- /dev/null +++ b/storage/client/file/src/samples/java/com/azure/file/DirectorySample.java @@ -0,0 +1,115 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.file; + +import com.azure.core.http.rest.Response; +import com.azure.core.util.configuration.ConfigurationManager; +import com.azure.storage.file.DirectoryClient; +import com.azure.storage.file.DirectoryClientBuilder; +import com.azure.storage.file.ShareClient; +import com.azure.storage.file.ShareClientBuilder; +import com.azure.storage.file.models.DirectoryProperties; +import com.azure.storage.file.models.StorageErrorException; +import java.util.UUID; + +/** + * Sample demonstrates how to create, list and delete directory and its subdirectories and files + * and how to get and set properties. + */ +public class DirectorySample { + private static final String ENDPOINT = ConfigurationManager.getConfiguration().get("AZURE_STORAGE_FILE_ENDPOINT"); + + // This is the helper method to generate random name. + private static String generateRandomName() { + return UUID.randomUUID().toString().substring(0, 8); + } + + /** + * The main method shows how to do the basic operation using directory sync client. + * @param args No args needed for the main method. + */ + public static void main(String[] args) { + String shareName = generateRandomName(); + ShareClient shareClient = new ShareClientBuilder().endpoint(ENDPOINT).shareName(shareName).buildClient(); + shareClient.create(); + // Build up a directory client + DirectoryClient directoryClient = new DirectoryClientBuilder().endpoint(ENDPOINT).shareName(generateRandomName()) + .shareName(shareName) + .directoryPath(generateRandomName()).buildClient(); + // Create a parent directory + try { + directoryClient.create(); + } catch (StorageErrorException e) { + System.out.println("Failed to create a directory. Reasons: " + e.getMessage()); + } + + // Create a child directory. + String childDirectoryName = generateRandomName(); + try { + directoryClient.createSubDirectory(childDirectoryName); + } catch (StorageErrorException e) { + System.out.println("Failed to create sub directory. Reasons: " + e.getMessage()); + } + + // Create a 1KB file under the child directory. + DirectoryClient childDirClient = null; + String fileName = generateRandomName(); + try { + childDirClient = directoryClient.getSubDirectoryClient(childDirectoryName); + childDirClient.createFile(fileName, 1024); + } catch (StorageErrorException e) { + System.out.println("Failed to create a file under the child directory. Reasons: " + e.getMessage()); + } + + // Delete the child directory. The operation will fail because storage service only allowed to delete the empty directory. + try { + childDirClient.delete(); + } catch (StorageErrorException e) { + System.out.println("This is expected as the child directory is not empty."); + } + + // List all the sub directories and files. + try { + directoryClient.listFilesAndDirectories().forEach( + fileRef -> { + System.out.printf("Is the resource a directory? %b. The resource name is: ", fileRef.isDirectory(), + fileRef.name()); + } + ); + } catch (StorageErrorException e) { + System.out.println("Failed to list all the subdirectories and files. Reasons: " + e.getMessage()); + } + + // Get the parent directory properties. + try { + Response propertiesResponse = directoryClient.getProperties(); + System.out.printf("This is the eTag %s of the directory: ", propertiesResponse.value().eTag()); + } catch (StorageErrorException e) { + System.out.println("Failed to get the properties of the parent directory"); + } + + // Delete the file. + try { + childDirClient.deleteFile(fileName); + } catch (StorageErrorException e) { + System.out.println("Failed to delete the file. Reasons: " + e.getMessage()); + } + + // Delete the child folder + try { + directoryClient.deleteSubDirectory(childDirectoryName); + } catch (StorageErrorException e) { + System.out.println("Failed to delete the child directory. Reasons: " + e.getMessage()); + } + + // Delete the parent folder + try { + directoryClient.delete(); + } catch (StorageErrorException e) { + System.out.println("Failed to delete the parent directory. Reasons: " + e.getMessage()); + } + + shareClient.delete(); + } + +} diff --git a/storage/client/file/src/samples/java/com/azure/file/FileSample.java b/storage/client/file/src/samples/java/com/azure/file/FileSample.java new file mode 100644 index 0000000000000..bff249f71e43c --- /dev/null +++ b/storage/client/file/src/samples/java/com/azure/file/FileSample.java @@ -0,0 +1,144 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.file; + +import com.azure.core.http.rest.Response; +import com.azure.core.util.configuration.ConfigurationManager; +import com.azure.storage.file.FileClient; +import com.azure.storage.file.FileClientBuilder; +import com.azure.storage.file.ShareClient; +import com.azure.storage.file.ShareClientBuilder; +import com.azure.storage.file.models.CopyStatusType; +import com.azure.storage.file.models.FileCopyInfo; +import com.azure.storage.file.models.FileProperties; +import com.azure.storage.file.models.StorageErrorException; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.util.UUID; + +/** + * Sample demonstrates how to create, copy and delete a file and how to get and set properties. + */ +public class FileSample { + private static final String ENDPOINT = ConfigurationManager.getConfiguration().get("AZURE_STORAGE_FILE_ENDPOINT"); + + // This is the helper method to generate random name. + private static String generateRandomName() { + return UUID.randomUUID().toString().substring(0, 8); + } + + /** + * The main method shows how to do the base operation using file sync client. + * @param args No args needed for the main method. + * @throws RuntimeException If error occurs when make storage API call. + * @throws Exception If there are any IO exception occurs. + */ + public static void main(String[] args) throws Exception { + String shareName = generateRandomName(); + ShareClient shareClient = new ShareClientBuilder().endpoint(ENDPOINT).shareName(shareName).buildClient(); + shareClient.create(); + String parentDirName = generateRandomName(); + shareClient.createDirectory(parentDirName); + + // Create a source file client + String srcFileName = generateRandomName(); + FileClient srcFileClient = new FileClientBuilder().endpoint(ENDPOINT).shareName(shareName) + .filePath(parentDirName + "/" + srcFileName).buildClient(); + + // Create a source file + try { + srcFileClient.create(1024); + } catch (StorageErrorException e) { + System.out.println("Failed to create source client. Reasons: " + e.getMessage()); + } + + // Upload some data bytes to the src file. + String dataText = "Hello, file client sample!"; + ByteBuf uploadData = Unpooled.wrappedBuffer(dataText.getBytes(StandardCharsets.UTF_8)); + try { + srcFileClient.upload(uploadData, uploadData.readableBytes()); + } catch (StorageErrorException e) { + System.out.println("Failed to upload the data. Reasons: " + e.getMessage()); + } + // Create a destination file client. + String destFileName = generateRandomName(); + FileClient destFileClient = new FileClientBuilder().endpoint(ENDPOINT).shareName(shareName) + .filePath(parentDirName + "/" + destFileName).buildClient(); + destFileClient.create(1024); + + // Copy the file from source file to destination file. + URL clientURL = null; + clientURL = srcFileClient.getFileUrl(); + + String sourceURL = clientURL.toString() + "/" + shareName + "/" + parentDirName + "/" + srcFileName; + + Response copyResponse = null; + try { + copyResponse = destFileClient.startCopy(sourceURL, null); + } catch (StorageErrorException e) { + throw new RuntimeException("Failed to start the copy of source file. Reasons: " + e.getMessage()); + } + + // Abort the copy if the status is pending. + if (copyResponse.value().copyStatus() == CopyStatusType.PENDING) { + try { + destFileClient.abortCopy(copyResponse.value().copyId()); + } catch (StorageErrorException e) { + System.out.println("Failed to abort the copy. Reasons: " + e.getMessage()); + } + } + + // Upload a local file to the storage. + URL fileFolder = FileSample.class.getClassLoader().getResource("."); + String uploadPath = fileFolder.getPath() + "testfiles/" + "uploadSample.txt"; + + try { + srcFileClient.uploadFromFile(uploadPath); + } catch (StorageErrorException e) { + System.out.println("Failed to upload file to storage. Reasons: " + e.getMessage()); + } + + // Download storage file to local file. + String downloadPath = fileFolder.getPath() + "testfiles/" + "downloadSample.txt"; + File downloadFile = new File(downloadPath); + try { + if (!Files.exists(downloadFile.toPath())) { + downloadFile.createNewFile(); + } + } catch (IOException e) { + throw new RuntimeException("Failed to create new upload file."); + } + try { + srcFileClient.downloadToFile(downloadPath); + } catch (StorageErrorException e) { + System.out.println("Failed to download file from storage. Reasons: " + e.getMessage()); + } + + if (!Files.exists(downloadFile.toPath())) { + downloadFile.delete(); + } + + // Get the file properties + try { + Response propertiesResponse = srcFileClient.getProperties(); + System.out.printf("This is the eTag: %s of the file. File type is : %s.", propertiesResponse.value().eTag(), propertiesResponse.value().fileType()); + } catch (StorageErrorException e) { + System.out.println("Failed to get file properties. Reasons: " + e.getMessage()); + } + + // Delete the source file. + try { + srcFileClient.delete(); + } catch (StorageErrorException e) { + System.out.println("Failed to delete the src file. Reasons: " + e.getMessage()); + } + + // Delete the share + shareClient.delete(); + } +} diff --git a/storage/client/file/src/samples/java/com/azure/file/FileServiceSample.java b/storage/client/file/src/samples/java/com/azure/file/FileServiceSample.java new file mode 100644 index 0000000000000..f5fad2f7035aa --- /dev/null +++ b/storage/client/file/src/samples/java/com/azure/file/FileServiceSample.java @@ -0,0 +1,67 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.file; + +import com.azure.core.http.rest.Response; +import com.azure.core.util.configuration.ConfigurationManager; +import com.azure.storage.file.FileServiceClient; +import com.azure.storage.file.FileServiceClientBuilder; +import com.azure.storage.file.models.FileServiceProperties; +import com.azure.storage.file.models.StorageErrorException; +import java.util.UUID; + +/** + * Sample demonstrates how to create, list and delete shares, and get and set properties. + */ +public class FileServiceSample { + private static final String CONNECTION_STRING = ConfigurationManager.getConfiguration().get("AZURE_STORAGE_CONNECTION_STRING"); + + // This is the helper method to generate random name. + private static String generateRandomName() { + return UUID.randomUUID().toString().substring(0, 8); + } + + /** + * The main method shows how to do the base operation using file service sync client. + * @param args No args needed for the main method + */ + public static void main(String[] args) { + // Create a file service client. + FileServiceClient fileServiceClient = new FileServiceClientBuilder() + .connectionString(CONNECTION_STRING).buildClient(); + + // Create 3 shares + for (int i = 0; i < 3; i++) { + try { + fileServiceClient.createShare(generateRandomName()); + } catch (StorageErrorException e) { + System.out.printf("Failed to create share %d. Reasons: %s", i, e.getMessage()); + } + } + + // Get properties from the file service + try { + Response response = fileServiceClient.getProperties(); + + System.out.printf("Hour metrics enabled: %b, Minute metrics enabled: %b\n", + response.value().hourMetrics(), response.value().minuteMetrics()); + } catch (StorageErrorException e) { + System.out.println("Failed to get the account properties. Reasons: " + e.getMessage()); + } + // List all shares under file service and delete them. + fileServiceClient.listShares().forEach( + shareItem -> { + try { + System.out.printf("This is the share name: %s in the file account.\n", shareItem.name()); + fileServiceClient.deleteShare(shareItem.name()); + System.out.println("The share has been deleted from the storage file account!"); + } catch (StorageErrorException e) { + System.out.println("Failed to delete the share. Reasons: " + e.getMessage()); + } + } + ); + + // Delete all shares under file service + + } +} diff --git a/storage/client/file/src/samples/java/com/azure/file/ShareSample.java b/storage/client/file/src/samples/java/com/azure/file/ShareSample.java new file mode 100644 index 0000000000000..1d6e9db8ebabb --- /dev/null +++ b/storage/client/file/src/samples/java/com/azure/file/ShareSample.java @@ -0,0 +1,134 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.file; + +import com.azure.core.http.rest.Response; +import com.azure.core.util.configuration.ConfigurationManager; +import com.azure.storage.file.ShareClient; +import com.azure.storage.file.ShareClientBuilder; +import com.azure.storage.file.models.ShareProperties; +import com.azure.storage.file.models.StorageErrorException; +import java.util.UUID; + +/** + * Sample demonstrates how to create, list and delete shares, and get and set properties. + */ +public class ShareSample { + private static final String ENDPOINT = ConfigurationManager.getConfiguration().get("AZURE_STORAGE_FILE_ENDPOINT"); + + // This is the helper method to generate random name. + private static String generateRandomName() { + return UUID.randomUUID().toString().substring(0, 8); + } + + /** + * The main method shows how to do the base operation using share sync client. + * @param args No args needed for the main method + */ + public static void main(String[] args) { + // Build a share client + String shareName = generateRandomName(); + ShareClient shareClient = new ShareClientBuilder().endpoint(ENDPOINT). + shareName(shareName).buildClient(); + + // Create first snapshot on share. + String shareSnapshot1 = null; + try { + shareSnapshot1 = shareClient.createSnapshot().value().snapshot(); + } catch (StorageErrorException e) { + System.out.println("Failed to create snapshot on share. Reasons: " + e.getMessage()); + } + + // Create a share using teh share client + try { + shareClient.create(); + } catch (StorageErrorException e) { + System.out.printf("Failed to create the share %s with share client. Reasons: %s\n", shareName, e.getMessage()); + } + // Create 3 directories using share client + for (int i = 0; i < 3; i++) { + try { + shareClient.createDirectory(generateRandomName()); + } catch (StorageErrorException e) { + System.out.println("Failed to create directory using the share client. Reasons: " + e.getMessage()); + } + } + + // Create another snapshot on share. + String shareSnapshot2 = null; + try { + shareSnapshot2 = shareClient.createSnapshot().value().snapshot(); + } catch (StorageErrorException e) { + System.out.println("Failed to create snapshot on share. Reasons: " + e.getMessage()); + } + + // Create another directory after having the snapshot + try { + shareClient.createDirectory(generateRandomName()); + } catch (StorageErrorException e) { + System.out.println("Failed to create directory using the share client. Reasons: " + e.getMessage()); + } + + // Get the properties of the share with first snapshot. + ShareClient shareClientWithSnapshot1 = null; + try { + shareClientWithSnapshot1 = new ShareClientBuilder().endpoint(ENDPOINT) + .shareName(shareName).snapshot(shareSnapshot1).buildClient(); + Response shareProperties1 = shareClientWithSnapshot1.getProperties(); + System.out.println("This is the first snapshot eTag: " + shareProperties1.value().etag()); + } catch (StorageErrorException e) { + System.out.println("Failed to get properties for the first share snapshot. Reasons: " + e.getMessage()); + } + + // Get the properties of the share with second snapshot. + ShareClient shareClientWithSnapshot2 = null; + try { + shareClientWithSnapshot2 = new ShareClientBuilder().endpoint(ENDPOINT) + .shareName(shareName).snapshot(shareSnapshot2).buildClient(); + Response shareProperties2 = shareClientWithSnapshot2.getProperties(); + System.out.println("This is the second snapshot eTag: " + shareProperties2.value().etag()); + } catch (StorageErrorException e) { + System.out.println("Failed to get properties for the second share snapshot. Reasons: " + e.getMessage()); + } + + // Get the root directory and list all directories. + try { + shareClient.getRootDirectoryClient().listFilesAndDirectories().forEach( + fileRef -> { + System.out.printf("Is the resource a file or directory?"); + } + ); + } catch (StorageErrorException e) { + System.out.println("Failed to delete the share. Reasons: " + e.getMessage()); + } + + // Delete the share snapshot 1 + try { + shareClientWithSnapshot1.delete(); + } catch (StorageErrorException e) { + System.out.println("Failed to delete the share snapshot 1. Reasons: " + e.getMessage()); + } + + // Check the delete share snapshot properties. + try { + shareClientWithSnapshot1.getProperties(); + } catch (StorageErrorException e) { + System.out.println("This is expected. The snapshot has been delete. Reasons: " + e.getMessage()); + } + + // Check the one not deleted. + try { + shareClientWithSnapshot2.getProperties(); + } catch (StorageErrorException e) { + System.out.println("Failed to get the properties of share snapshot 2. Reasons: " + e.getMessage()); + } + + // Delete the share. + try { + shareClient.delete(); + } catch (StorageErrorException e) { + System.out.println("Failed to delete the share. Reasons: " + e.getMessage()); + } + + } +} diff --git a/storage/client/file/src/samples/java/com/azure/storage/file/DirectoryJavaDocCodeSamples.java b/storage/client/file/src/samples/java/com/azure/storage/file/DirectoryJavaDocCodeSamples.java new file mode 100644 index 0000000000000..ff06ab021ca03 --- /dev/null +++ b/storage/client/file/src/samples/java/com/azure/storage/file/DirectoryJavaDocCodeSamples.java @@ -0,0 +1,586 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.storage.file; + +import com.azure.core.http.rest.Response; +import com.azure.core.http.rest.VoidResponse; +import com.azure.storage.common.credentials.SASTokenCredential; +import com.azure.storage.common.credentials.SharedKeyCredential; +import com.azure.storage.file.models.DirectoryInfo; +import com.azure.storage.file.models.DirectoryProperties; +import com.azure.storage.file.models.DirectorySetMetadataInfo; +import com.azure.storage.file.models.FileHTTPHeaders; +import com.azure.storage.file.models.HandleItem; +import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.util.Collections; +import java.util.Map; + +/** + * Contains code snippets when generating javadocs through doclets for {@link DirectoryClient} and {@link DirectoryAsyncClient}. + */ +public class DirectoryJavaDocCodeSamples { + /** + * Generates code sample for {@link DirectoryClient} instantiation. + */ + public void initialization() { + // BEGIN: com.azure.storage.file.directoryClient.instantiation + DirectoryClient client = new DirectoryClientBuilder() + .connectionString("${connectionString}") + .endpoint("${endpoint}") + .buildClient(); + // END: com.azure.storage.file.directoryClient.instantiation + } + + /** + * Generates code sample for {@link DirectoryAsyncClient} instantiation. + */ + public void asyncInitialization() { + // BEGIN: com.azure.storage.file.directoryAsyncClient.instantiation + DirectoryAsyncClient client = new DirectoryClientBuilder() + .connectionString("${connectionString}") + .endpoint("${endpoint}") + .buildAsyncClient(); + // END: com.azure.storage.file.directoryAsyncClient.instantiation + } + + /** + * Generates code sample for creating a {@link DirectoryClient} with {@link SASTokenCredential} + * @return An instance of {@link DirectoryClient} + */ + public DirectoryClient createClientWithSASToken() { + // BEGIN: com.azure.storage.file.directoryClient.instantiation.sastoken + DirectoryClient directoryClient = new DirectoryClientBuilder() + .endpoint("https://${accountName}.file.core.windows.net?${SASToken}") + .shareName("myshare") + .directoryPath("mydirectory") + .buildClient(); + // END: com.azure.storage.file.directoryClient.instantiation.sastoken + return directoryClient; + } + + /** + * Generates code sample for creating a {@link DirectoryAsyncClient} with {@link SASTokenCredential} + * @return An instance of {@link DirectoryAsyncClient} + */ + public DirectoryAsyncClient createAsyncClientWithSASToken() { + // BEGIN: com.azure.storage.file.directoryAsyncClient.instantiation.sastoken + DirectoryAsyncClient directoryAsyncClient = new DirectoryClientBuilder() + .endpoint("https://{accountName}.file.core.windows.net?{SASToken}") + .shareName("myshare") + .directoryPath("mydirectory") + .buildAsyncClient(); + // END: com.azure.storage.file.directoryAsyncClient.instantiation.sastoken + return directoryAsyncClient; + } + + /** + * Generates code sample for creating a {@link DirectoryClient} with {@link SASTokenCredential} + * @return An instance of {@link DirectoryClient} + */ + public DirectoryClient createClientWithCredential() { + + // BEGIN: com.azure.storage.file.directoryClient.instantiation.credential + DirectoryClient directoryClient = new DirectoryClientBuilder() + .endpoint("https://${accountName}.file.core.windows.net") + .credential(SASTokenCredential.fromQuery("${SASTokenQueryParams}")) + .shareName("myshare") + .directoryPath("mydirectory") + .buildClient(); + // END: com.azure.storage.file.directoryClient.instantiation.credential + return directoryClient; + } + + /** + * Generates code sample for creating a {@link DirectoryAsyncClient} with {@link SASTokenCredential} + * @return An instance of {@link DirectoryAsyncClient} + */ + public DirectoryAsyncClient createAsyncClientWithCredential() { + // BEGIN: com.azure.storage.file.directoryAsyncClient.instantiation.credential + DirectoryAsyncClient direcotryAsyncClient = new DirectoryClientBuilder() + .endpoint("https://{accountName}.file.core.windows.net") + .credential(SASTokenCredential.fromQuery("${SASTokenQueryParams}")) + .shareName("myshare") + .directoryPath("mydirectory") + .buildAsyncClient(); + // END: com.azure.storage.file.directoryAsyncClient.instantiation.credential + return direcotryAsyncClient; + } + + /** + * Generates code sample for creating a {@link DirectoryClient} with {@code connectionString} which turns into {@link SharedKeyCredential} + * @return An instance of {@link DirectoryClient} + */ + public DirectoryClient createClientWithConnectionString() { + // BEGIN: com.azure.storage.file.directoryClient.instantiation.connectionstring + String connectionString = "DefaultEndpointsProtocol=https;AccountName={name};AccountKey={key}" + + ";EndpointSuffix={core.windows.net}"; + DirectoryClient directoryClient = new DirectoryClientBuilder() + .connectionString(connectionString).shareName("myshare").directoryPath("mydirectory") + .buildClient(); + // END: com.azure.storage.file.directoryClient.instantiation.connectionstring + return directoryClient; + } + + /** + * Generates code sample for creating a {@link DirectoryAsyncClient} with {@code connectionString} which turns into {@link SharedKeyCredential} + * @return An instance of {@link DirectoryAsyncClient} + */ + public DirectoryAsyncClient createAsyncClientWithConnectionString() { + // BEGIN: com.azure.storage.file.directoryAsyncClient.instantiation.connectionstring + String connectionString = "DefaultEndpointsProtocol=https;AccountName={name};AccountKey={key};" + + "EndpointSuffix={core.windows.net}"; + DirectoryAsyncClient directoryAsyncClient = new DirectoryClientBuilder() + .connectionString(connectionString).shareName("myshare").directoryPath("mydirectory") + .buildAsyncClient(); + // END: com.azure.storage.file.directoryAsyncClient.instantiation.connectionstring + return directoryAsyncClient; + } + + /** + * Generates a code sample for using {@link DirectoryClient#create()} + */ + public void createDirectory() { + DirectoryClient directoryClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.directoryClient.createDirectory + Response response = directoryClient.create(); + System.out.println("Complete creating the directory with status code: " + response.statusCode()); + // END: com.azure.storage.file.directoryClient.createDirectory + } + + /** + * Generates a code sample for using {@link DirectoryAsyncClient#create} + */ + public void createDirectoryAsync() { + DirectoryAsyncClient directoryAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.directoryAsyncClient.create + directoryAsyncClient.create().subscribe( + response -> { }, + error -> System.err.print(error.toString()), + () -> System.out.println("Complete creating the directory!") + ); + // END: com.azure.storage.file.directoryAsyncClient.create + } + + /** + * Generates a code sample for using {@link DirectoryClient#create(Map)} + */ + public void createDirectoryWithOverload() { + DirectoryClient directoryClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.directoryClient.create#map + Response response = directoryClient.create(Collections.singletonMap("directory", "metadata")); + System.out.println("Complete creating the directory with status code: " + response.statusCode()); + // END: com.azure.storage.file.directoryClient.create#map + } + + /** + * Generates a code sample for using {@link DirectoryAsyncClient#create(Map)} + */ + public void createDirectoryAsyncWithOverload() { + DirectoryAsyncClient directoryAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.directoryAsyncClient.create#map + directoryAsyncClient.create(Collections.singletonMap("directory", "metadata")).subscribe( + response -> System.out.printf("Creating the directory completed with status code %d", + response.statusCode()), + error -> System.err.print(error.toString()), + () -> System.out.println("Complete creating the directory!") + ); + // END: com.azure.storage.file.directoryAsyncClient.create#map + } + + /** + * Generates a code sample for using {@link DirectoryClient#createSubDirectory(String) + */ + public void createSubDirectory() { + DirectoryClient directoryClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.directoryClient.createSubDirectory#string + Response response = directoryClient.createSubDirectory("subdir"); + System.out.println("Complete creating the subdirectory with status code " + response.statusCode()); + // END: com.azure.storage.file.directoryClient.createSubDirectory#string + } + + /** + * Generates a code sample for using {@link DirectoryAsyncClient#createSubDirectory(String)} + */ + public void createSubDirectoryAsync() { + DirectoryAsyncClient directoryAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.directoryAsyncClient.createSubDirectory#string + directoryAsyncClient.createSubDirectory("subdir").subscribe( + response -> System.out.println("Successfully creating the subdirectory with status code: " + + response.statusCode()), + error -> System.err.println(error.toString()), + () -> System.out.println("Complete creating the sub directory.") + ); + // END: com.azure.storage.file.directoryAsyncClient.createSubDirectory#string + } + + /** + * Generates a code sample for using {@link DirectoryClient#createSubDirectory(String, Map)} + */ + public void createSubDirectoryMaxOverload() { + DirectoryClient directoryClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.directoryClient.createSubDirectory#string-map + Response response = directoryClient.createSubDirectory("subdir", + Collections.singletonMap("directory", "metadata")); + System.out.printf("Creating the sub directory completed with status code %d", response.statusCode()); + // END: com.azure.storage.file.directoryClient.createSubDirectory#string-map + } + + /** + * Generates a code sample for using {@link DirectoryAsyncClient#createSubDirectory(String, Map)} + */ + public void createSubDirectoryAsyncMaxOverload() { + DirectoryAsyncClient directoryAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.directoryAsyncClient.createSubDirectory#string-map + directoryAsyncClient.createSubDirectory("subdir", + Collections.singletonMap("directory", "metadata")) + .subscribe(response -> System.out.printf("Creating the subdirectory completed with status code %d", + response.statusCode())); + // END: com.azure.storage.file.directoryAsyncClient.createSubDirectory#string-map + } + + /** + * Generates a code sample for using {@link DirectoryClient#createFile(String, long)} + */ + public void createFile() { + DirectoryClient directoryClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.directoryClient.createFile#string-long + Response response = directoryClient.createFile("myfile", 1024); + System.out.println("Complete creating the file with status code: " + response.statusCode()); + // END: com.azure.storage.file.directoryClient.createFile#string-long + } + + /** + * Generates a code sample for using {@link DirectoryAsyncClient#createFile(String, long)} + */ + public void createFileAsync() { + DirectoryAsyncClient directoryAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.directoryAsyncClient.createFile#string-long + directoryAsyncClient.createFile("myfile", 1024).subscribe( + response -> { }, + error -> System.err.println(error.toString()), + () -> System.out.println("Complete creating the file.") + ); + // END: com.azure.storage.file.directoryAsyncClient.createFile#string-long + } + + /** + * Generates a code sample for using {@link DirectoryClient#createFile(String, long, FileHTTPHeaders, Map)} + */ + public void createFileMaxOverload() { + DirectoryClient directoryClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.directoryClient.createFile#string-long-fileHTTPHeaders-map + FileHTTPHeaders httpHeaders = new FileHTTPHeaders().fileContentType("text/plain"); + Response response = directoryClient.createFile("myFile", 1024, + httpHeaders, Collections.singletonMap("directory", "metadata")); + System.out.println("Complete creating the file with status code: " + response.statusCode()); + // END: com.azure.storage.file.directoryClient.createFile#string-long-fileHTTPHeaders-map + } + + /** + * Generates a code sample for using {@link DirectoryAsyncClient#createFile(String, long, FileHTTPHeaders, Map)} + */ + public void createFileAsyncMaxOverload() { + DirectoryAsyncClient directoryAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.directoryAsyncClient.createFile#string-long-fileHTTPHeaders-map + FileHTTPHeaders httpHeaders = new FileHTTPHeaders().fileContentType("text/plain"); + directoryAsyncClient.createFile("myFile", 1024, httpHeaders, + Collections.singletonMap("directory", "metadata")).subscribe( + response -> System.out.printf("Creating the file completed with status code %d", response.statusCode()), + error -> System.err.println(error.toString()), + () -> System.out.println("Complete creating the file.") + ); + // END: com.azure.storage.file.directoryAsyncClient.createFile#string-long-fileHTTPHeaders-map + } + + /** + * Generates a code sample for using {@link DirectoryClient#listFilesAndDirectories()} + */ + public void listDirectoriesAndFiles() { + DirectoryClient directoryClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.directoryClient.listFilesAndDirectories + directoryClient.listFilesAndDirectories().forEach( + fileRef -> System.out.printf("Is the resource a directory? %b. The resource name is: %s.", + fileRef.isDirectory(), fileRef.name()) + ); + // END: com.azure.storage.file.directoryClient.listFilesAndDirectories + } + + /** + * Generates a code sample for using {@link DirectoryAsyncClient#listFilesAndDirectories()} + */ + public void listDirectoriesAndFilesAsync() { + DirectoryAsyncClient directoryAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.directoryAsyncClient.listFilesAndDirectories + directoryAsyncClient.listFilesAndDirectories().subscribe( + fileRef -> System.out.printf("Is the resource a directory? %b. The resource name is: %s.", + fileRef.isDirectory(), fileRef.name()), + error -> System.err.println(error.toString()), + () -> System.out.println("Complete listing the directories and files.") + ); + // END: com.azure.storage.file.directoryAsyncClient.listFilesAndDirectories + } + + /** + * Generates a code sample for using {@link DirectoryClient#listFilesAndDirectories(String, Integer)} + */ + public void listDirectoriesAndFilesMaxOverload() { + DirectoryClient directoryClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.directoryClient.listFilesAndDirectories#string-integer + directoryClient.listFilesAndDirectories("subdir", 10).forEach( + fileRef -> System.out.printf("Is the resource a directory? %b. The resource name is: %s.", + fileRef.isDirectory(), fileRef.name()) + ); + // END: com.azure.storage.file.directoryClient.listFilesAndDirectories#string-integer + } + + + /** + * Generates a code sample for using {@link DirectoryAsyncClient#listFilesAndDirectories(String, Integer)} + */ + public void listDirectoriesAndFilesAsyncMaxOverload() { + DirectoryAsyncClient directoryAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.directoryAsyncClient.listFilesAndDirectories#string-integer + directoryAsyncClient.listFilesAndDirectories("subdir", 10).subscribe( + fileRef -> System.out.printf("Is the resource a directory? %b. The resource name is: %s.", + fileRef.isDirectory(), fileRef.name()), + error -> System.err.println(error.toString()), + () -> System.out.println("Complete listing the directories and files.") + ); + // END: com.azure.storage.file.directoryAsyncClient.listFilesAndDirectories#string-integer + } + + /** + * Generates a code sample for using {@link DirectoryClient#deleteFile(String)} ()} + */ + public void deleteFile() { + DirectoryClient directoryClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.directoryClient.deleteFile#string + VoidResponse response = directoryClient.deleteFile("myfile"); + System.out.println("Complete deleting the file with status code: " + response.statusCode()); + // END: com.azure.storage.file.directoryClient.deleteFile#string + } + + /** + * Generates a code sample for using {@link DirectoryAsyncClient#deleteFile(String)} ()} + */ + public void deleteFileAsync() { + DirectoryAsyncClient directoryAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.directoryAsyncClient.deleteFile#string + directoryAsyncClient.deleteFile("myfile").subscribe( + response -> { }, + error -> System.err.println(error.toString()), + () -> System.out.println("Complete deleting the file.") + ); + // END: com.azure.storage.file.directoryAsyncClient.deleteFile#string + } + + /** + * Generates a code sample for using {@link DirectoryClient#deleteSubDirectory(String)} + */ + public void deleteSubDirectory() { + DirectoryClient directoryClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.directoryClient.deleteSubDirectory#string + VoidResponse response = directoryClient.deleteSubDirectory("mysubdirectory"); + System.out.println("Complete deleting the subdirectory with status code: " + response.statusCode()); + // END: com.azure.storage.file.directoryClient.deleteSubDirectory#string + } + + /** + * Generates a code sample for using {@link DirectoryAsyncClient#deleteSubDirectory(String)} ()} + */ + public void deleteSubDirectoryAsync() { + DirectoryAsyncClient directoryAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.directoryAsyncClient.deleteSubDirectory#string + directoryAsyncClient.deleteSubDirectory("mysubdirectory").subscribe( + response -> { }, + error -> System.err.println(error.toString()), + () -> System.out.println("Complete deleting the subdirectory.") + ); + // END: com.azure.storage.file.directoryAsyncClient.deleteSubDirectory#string + } + + /** + * Generates a code sample for using {@link DirectoryClient#delete()} ()} + */ + public void deleteDirectory() { + DirectoryClient directoryClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.directoryClient.delete + VoidResponse response = directoryClient.delete(); + System.out.println("Complete deleting the file with status code: " + response.statusCode()); + // END: com.azure.storage.file.directoryClient.delete + } + + /** + * Generates a code sample for using {@link DirectoryAsyncClient#delete()} + */ + public void deleteDirectoryAsync() { + DirectoryAsyncClient directoryAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.directoryAsyncClient.delete + directoryAsyncClient.delete().subscribe( + response -> { }, + error -> System.err.println(error.toString()), + () -> System.out.println("Complete deleting the file.") + ); + // END: com.azure.storage.file.directoryAsyncClient.delete + } + + /** + * Generates a code sample for using {@link DirectoryClient#getProperties()} + */ + public void getProperties() { + DirectoryClient directoryClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.directoryClient.getProperties + Response response = directoryClient.getProperties(); + System.out.printf("Directory latest modified date is %s.", response.value().lastModified()); + // END: com.azure.storage.file.directoryClient.getProperties + } + + /** + * Generates a code sample for using {@link DirectoryAsyncClient#getProperties()} + */ + public void getPropertiesAsync() { + DirectoryAsyncClient directoryAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.directoryAsyncClient.getProperties + directoryAsyncClient.getProperties() + .subscribe(response -> { + DirectoryProperties properties = response.value(); + System.out.printf("Directory latest modified date is %s.", properties.lastModified()); + }); + // END: com.azure.storage.file.directoryAsyncClient.getProperties + } + + /** + * Generates a code sample for using {@link DirectoryClient#setMetadata(Map)} + */ + public void setMetadata() { + DirectoryClient directoryClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.directoryClient.setMetadata#map + Response response = + directoryClient.setMetadata(Collections.singletonMap("directory", "updatedMetadata")); + System.out.printf("Setting the directory metadata completed with status code %d", response.statusCode()); + // END: com.azure.storage.file.directoryClient.setMetadata#map + } + + /** + * Generates a code sample for using {@link DirectoryAsyncClient#setMetadata(Map)} + */ + public void setMetadataAsync() { + DirectoryAsyncClient directoryAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.directoryAsyncClient.setMetadata#map + directoryAsyncClient.setMetadata(Collections.singletonMap("directory", "updatedMetadata")) + .subscribe(response -> System.out.printf("Setting the directory metadata completed with status code %d", + response.statusCode())); + // END: com.azure.storage.file.directoryAsyncClient.setMetadata#map + } + + /** + * Generates a code sample for using {@link DirectoryClient#setMetadata(Map)} to clear the metadata. + */ + public void clearMetadata() { + DirectoryClient directoryClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.directoryClient.setMetadata#map.clearMetadata + Response response = directoryClient.setMetadata(null); + System.out.printf("Directory latest modified date is %s.", response.statusCode()); + // END: com.azure.storage.file.directoryClient.setMetadata#map.clearMetadata + } + + /** + * Generates a code sample for using {@link DirectoryAsyncClient#setMetadata(Map)} to clear the metadata. + */ + public void clearMetadataAsync() { + DirectoryAsyncClient directoryAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.directoryAsyncClient.setMetadata#map.clearMetadata + directoryAsyncClient.setMetadata(null) + .subscribe(response -> System.out.printf("Clearing the directory metadata completed with status code %d", + response.statusCode())); + // END: com.azure.storage.file.directoryAsyncClient.setMetadata#map.clearMetadata + } + + /** + * Generates a code sample for using {@link DirectoryClient#getHandles(Integer, boolean)} + */ + public void getHandles() { + DirectoryClient directoryClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.directoryClient.getHandles + Iterable result = directoryClient.getHandles(10, true); + System.out.printf("Get handles completed with handle id %s", result.iterator().next().handleId()); + // END: com.azure.storage.file.directoryClient.getHandles + } + + /** + * Generates a code sample for using {@link DirectoryAsyncClient#getHandles(Integer, boolean)} + */ + public void getHandlesAsync() { + DirectoryAsyncClient directoryAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.directoryAsyncClient.getHandles + directoryAsyncClient.getHandles(10, true) + .subscribe(handleItem -> System.out.printf("Get handles completed with handle id %s", + handleItem.handleId())); + // END: com.azure.storage.file.directoryAsyncClient.getHandles + } + + /** + * Generates a code sample for using {@link DirectoryClient#forceCloseHandles(String, boolean)} + */ + public void forceCloseHandles() { + DirectoryClient directoryClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.directoryClient.forceCloseHandles + Iterable result = directoryClient.getHandles(10, true); + result.forEach(handleItem -> { + directoryClient.forceCloseHandles(handleItem.handleId(), true).forEach(numOfClosedHandles -> + System.out.printf("Get handles completed with handle id %s", handleItem.handleId())); + }); + // END: com.azure.storage.file.directoryClient.forceCloseHandles + } + + /** + * Generates a code sample for using {@link DirectoryAsyncClient#forceCloseHandles(String, boolean)} + */ + public void forceCloseHandlesAsync() { + DirectoryAsyncClient directoryAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.directoryAsyncClient.forceCloseHandles + directoryAsyncClient.getHandles(10, true) + .subscribe(handleItem -> { + directoryAsyncClient.forceCloseHandles(handleItem.handleId(), true) + .subscribe(numOfClosedHandles -> + System.out.printf("Close %d handles.", numOfClosedHandles)); + }); + // END: com.azure.storage.file.directoryAsyncClient.forceCloseHandles + } + + /** + * Generates a code sample for using {@link DirectoryClient#getShareSnapshotId()} + */ + public void getShareSnapshotId() { + // BEGIN: com.azure.storage.file.directoryClient.getShareSnapshotId + OffsetDateTime currentTime = OffsetDateTime.of(LocalDateTime.now(), ZoneOffset.UTC); + DirectoryClient directoryClient = new DirectoryClientBuilder() + .endpoint("https://${accountName}.file.core.windows.net") + .credential(SASTokenCredential.fromQuery("${SASToken}")) + .shareName("myshare") + .directoryPath("mydirectory") + .snapshot(currentTime.toString()) + .buildClient(); + directoryClient.getShareSnapshotId(); + // END: com.azure.storage.file.directoryClient.getShareSnapshotId + } + + /** + * Generates a code sample for using {@link DirectoryAsyncClient#getShareSnapshotId()} + */ + public void getShareSnapshotIdAsync() { + // BEGIN: com.azure.storage.file.directoryAsyncClient.getShareSnapshotId + OffsetDateTime currentTime = OffsetDateTime.of(LocalDateTime.now(), ZoneOffset.UTC); + DirectoryAsyncClient directoryAsyncClient = new DirectoryClientBuilder() + .endpoint("https://${accountName}.file.core.windows.net") + .credential(SASTokenCredential.fromQuery("${SASToken}")) + .shareName("myshare") + .directoryPath("mydirectory") + .snapshot(currentTime.toString()) + .buildAsyncClient(); + directoryAsyncClient.getShareSnapshotId(); + // END: com.azure.storage.file.directoryAsyncClient.getShareSnapshotId + } +} diff --git a/storage/client/file/src/samples/java/com/azure/storage/file/FileJavaDocCodeSamples.java b/storage/client/file/src/samples/java/com/azure/storage/file/FileJavaDocCodeSamples.java new file mode 100644 index 0000000000000..146abbe97d04b --- /dev/null +++ b/storage/client/file/src/samples/java/com/azure/storage/file/FileJavaDocCodeSamples.java @@ -0,0 +1,785 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.storage.file; + +import com.azure.core.http.rest.Response; +import com.azure.core.http.rest.VoidResponse; +import com.azure.storage.common.credentials.SASTokenCredential; +import com.azure.storage.common.credentials.SharedKeyCredential; +import com.azure.storage.file.models.FileCopyInfo; +import com.azure.storage.file.models.FileDownloadInfo; +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.FileRange; +import com.azure.storage.file.models.FileRangeWriteType; +import com.azure.storage.file.models.FileUploadInfo; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.util.Collections; +import java.util.Map; +import reactor.core.publisher.Flux; + +/** + * Contains code snippets when generating javadocs through doclets for {@link FileClient} and {@link FileAsyncClient}. + */ +public class FileJavaDocCodeSamples { + /** + * Generates code sample for {@link FileClient} instantiation. + */ + public void initialization() { + // BEGIN: com.azure.storage.file.fileClient.instantiation + FileClient client = new FileClientBuilder() + .connectionString("${connectionString}") + .endpoint("${endpoint}") + .buildClient(); + // END: com.azure.storage.file.fileClient.instantiation + } + + /** + * Generates code sample for {@link FileAsyncClient} instantiation. + */ + public void asyncInitialization() { + // BEGIN: com.azure.storage.file.fileAsyncClient.instantiation + FileAsyncClient client = new FileClientBuilder() + .connectionString("${connectionString}") + .endpoint("${endpoint}") + .buildAsyncClient(); + // END: com.azure.storage.file.fileAsyncClient.instantiation + } + + /** + * Generates code sample for creating a {@link FileClient} with {@link SASTokenCredential} + * @return An instance of {@link FileClient} + */ + public FileClient createClientWithSASToken() { + + // BEGIN: com.azure.storage.file.fileClient.instantiation.sastoken + FileClient fileClient = new FileClientBuilder() + .endpoint("https://${accountName}.file.core.windows.net?${SASToken}") + .shareName("myshare") + .filePath("myfilepath") + .buildClient(); + // END: com.azure.storage.file.fileClient.instantiation.sastoken + return fileClient; + } + + /** + * Generates code sample for creating a {@link FileAsyncClient} with {@link SASTokenCredential} + * @return An instance of {@link FileAsyncClient} + */ + public FileAsyncClient createAsyncClientWithSASToken() { + // BEGIN: com.azure.storage.file.fileAsyncClient.instantiation.sastoken + FileAsyncClient fileAsyncClient = new FileClientBuilder() + .endpoint("https://{accountName}.file.core.windows.net?{SASToken}") + .shareName("myshare") + .filePath("myfilepath") + .buildAsyncClient(); + // END: com.azure.storage.file.fileAsyncClient.instantiation.sastoken + return fileAsyncClient; + } + + /** + * Generates code sample for creating a {@link FileClient} with {@link SASTokenCredential} + * @return An instance of {@link FileClient} + */ + public FileClient createClientWithCredential() { + + // BEGIN: com.azure.storage.file.fileClient.instantiation.credential + FileClient fileClient = new FileClientBuilder() + .endpoint("https://${accountName}.file.core.windows.net") + .credential(SASTokenCredential.fromQuery("${SASTokenQueryParams}")) + .shareName("myshare") + .filePath("myfilepath") + .buildClient(); + // END: com.azure.storage.file.fileClient.instantiation.credential + return fileClient; + } + + /** + * Generates code sample for creating a {@link FileAsyncClient} with {@link SASTokenCredential} + * @return An instance of {@link FileAsyncClient} + */ + public FileAsyncClient createAsyncClientWithCredential() { + // BEGIN: com.azure.storage.file.fileAsyncClient.instantiation.credential + FileAsyncClient fileAsyncClient = new FileClientBuilder() + .endpoint("https://{accountName}.file.core.windows.net") + .credential(SASTokenCredential.fromQuery("${SASTokenQueryParams}")) + .shareName("myshare") + .filePath("myfilepath") + .buildAsyncClient(); + // END: com.azure.storage.file.fileAsyncClient.instantiation.credential + return fileAsyncClient; + } + + /** + * Generates code sample for creating a {@link FileClient} with {@code connectionString} which turns into {@link SharedKeyCredential} + * @return An instance of {@link FileClient} + */ + public FileClient createClientWithConnectionString() { + // BEGIN: com.azure.storage.file.fileClient.instantiation.connectionstring + String connectionString = "DefaultEndpointsProtocol=https;AccountName={name};AccountKey={key};" + + "EndpointSuffix={core.windows.net}"; + FileClient fileClient = new FileClientBuilder() + .connectionString(connectionString).shareName("myshare").filePath("myfilepath") + .buildClient(); + // END: com.azure.storage.file.fileClient.instantiation.connectionstring + return fileClient; + } + + /** + * Generates code sample for creating a {@link FileAsyncClient} with {@code connectionString} which turns into {@link SharedKeyCredential} + * @return An instance of {@link FileAsyncClient} + */ + public FileAsyncClient createAsyncClientWithConnectionString() { + // BEGIN: com.azure.storage.file.fileAsyncClient.instantiation.connectionstring + String connectionString = "DefaultEndpointsProtocol=https;AccountName={name};AccountKey={key};" + + "EndpointSuffix={core.windows.net}"; + FileAsyncClient fileAsyncClient = new FileClientBuilder() + .connectionString(connectionString).shareName("myshare").filePath("myfilepath") + .buildAsyncClient(); + // END: com.azure.storage.file.fileAsyncClient.instantiation.connectionstring + return fileAsyncClient; + } + + /** + * Generates a code sample for using {@link FileClient#create(long)} + */ + public void createFile() { + FileClient fileClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileClient.create + Response response = fileClient.create(1024); + System.out.println("Complete creating the file with status code: " + response.statusCode()); + // END: com.azure.storage.file.fileClient.create + } + + /** + * Generates a code sample for using {@link FileAsyncClient#create(long)} + */ + public void createFileAsync() { + FileAsyncClient fileAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileAsyncClient.create + fileAsyncClient.create(1024).subscribe( + response -> { }, + error -> System.err.print(error.toString()), + () -> System.out.println("Complete creating the file!") + ); + // END: com.azure.storage.file.fileAsyncClient.create + } + + /** + * Generates a code sample for using {@link FileClient#create(long, FileHTTPHeaders, Map)} + */ + public void createFileMaxOverload() { + FileClient fileClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileClient.create#long-filehttpheaders-map + FileHTTPHeaders httpHeaders = new FileHTTPHeaders().fileContentType("text/plain"); + Response response = fileClient.create(1024, httpHeaders, + Collections.singletonMap("file", "updatedMetadata")); + System.out.printf("Creating the file completed with status code %d", response.statusCode()); + // END: com.azure.storage.file.fileClient.create#long-filehttpheaders-map + } + + /** + * Generates a code sample for using {@link FileAsyncClient#create(long, FileHTTPHeaders, Map)} + */ + public void createFileAsyncMaxOverload() { + FileAsyncClient fileAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileAsyncClient.create#long-filehttpheaders-map + FileHTTPHeaders httpHeaders = new FileHTTPHeaders().fileContentType("text/plain"); + fileAsyncClient.create(1024, httpHeaders, Collections.singletonMap("file", "updatedMetadata")) + .subscribe(response -> System.out.printf("Creating the file completed with status code %d", + response.statusCode())); + // END: com.azure.storage.file.fileAsyncClient.create#long-filehttpheaders-map + } + + /** + * Generates a code sample for using {@link FileClient#startCopy(String, Map)} + */ + public void copyFile() { + FileClient fileClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileClient.startCopy#string-map + Response response = fileClient.startCopy( + "https://{accountName}.file.core.windows.net?{SASToken}", + Collections.singletonMap("file", "metadata")); + System.out.println("Complete copying the file with status code: " + response.statusCode()); + // END: com.azure.storage.file.fileClient.startCopy#string-map + } + + /** + * Generates a code sample for using {@link FileClient#startCopy(String, Map)} + */ + public void copyFileAsync() { + FileAsyncClient fileAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileAsyncClient.startCopy#string-map + fileAsyncClient.startCopy("https://{accountName}.file.core.windows.net?{SASToken}", + Collections.singletonMap("file", "metadata")).subscribe( + response -> System.out.println("Successfully copying the file with status code: " + response.statusCode()), + error -> System.err.println(error.toString()), + () -> System.out.println("Complete copying the file.") + ); + // END: com.azure.storage.file.fileAsyncClient.startCopy#string-map + } + + /** + * Generates a code sample for using {@link FileClient#abortCopy(String)} + */ + public void abortCopyFile() { + FileClient fileClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileClient.abortCopy#string + VoidResponse response = fileClient.abortCopy("someCopyId"); + System.out.printf("Abort copying the file completed with status code %d", response.statusCode()); + // END: com.azure.storage.file.fileClient.abortCopy#string + } + + /** + * Generates a code sample for using {@link FileClient#abortCopy(String)} + */ + public void abortCopyFileAsync() { + FileAsyncClient fileAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileAsyncClient.abortCopy#string + fileAsyncClient.abortCopy("someCopyId") + .subscribe(response -> System.out.printf("Abort copying the file completed with status code %d", + response.statusCode())); + // END: com.azure.storage.file.fileAsyncClient.abortCopy#string + } + + /** + * Generates a code sample for using {@link FileClient#upload(ByteBuf, long)} + */ + public void uploadData() { + FileClient fileClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileClient.upload#flux-long + ByteBuf defaultData = Unpooled.wrappedBuffer("default".getBytes(StandardCharsets.UTF_8)); + Response response = fileClient.upload(defaultData, defaultData.readableBytes()); + System.out.println("Complete uploading the data with status code: " + response.statusCode()); + // END: com.azure.storage.file.fileClient.upload#flux-long + } + + /** + * Generates a code sample for using {@link FileAsyncClient#upload(Flux, long)} + */ + public void uploadDataAsync() { + FileAsyncClient fileAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileAsyncClient.upload#flux-long + ByteBuf defaultData = Unpooled.wrappedBuffer("default".getBytes(StandardCharsets.UTF_8)); + fileAsyncClient.upload(Flux.just(defaultData), defaultData.readableBytes()).subscribe( + response -> { }, + error -> System.err.print(error.toString()), + () -> System.out.println("Complete deleting the file!") + ); + // END: com.azure.storage.file.fileAsyncClient.upload#flux-long + } + + /** + * Generates a code sample for using {@link FileClient#upload(ByteBuf, long, int, FileRangeWriteType)} + */ + public void uploadDataMaxOverload() { + FileClient fileClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileClient.upload#bytebuf-long-int-filerangewritetype + ByteBuf defaultData = Unpooled.wrappedBuffer("default".getBytes(StandardCharsets.UTF_8)); + Response response = fileClient.upload(defaultData, defaultData.readableBytes(), 1024, + FileRangeWriteType.UPDATE); + System.out.println("Complete uploading the data with status code: " + response.statusCode()); + // END: com.azure.storage.file.fileClient.upload#bytebuf-long-int-filerangewritetype + } + + /** + * Generates a code sample for using {@link FileAsyncClient#upload(Flux, long)} + */ + public void uploadDataAsyncMaxOverload() { + FileAsyncClient fileAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileAsyncClient.upload#bytebuf-long-int-filerangewritetype + ByteBuf defaultData = Unpooled.wrappedBuffer("default".getBytes(StandardCharsets.UTF_8)); + fileAsyncClient.upload(Flux.just(defaultData), defaultData.readableBytes(), 1024, + FileRangeWriteType.UPDATE).subscribe( + response -> { }, + error -> System.err.print(error.toString()), + () -> System.out.println("Complete deleting the file!") + ); + // END: com.azure.storage.file.fileAsyncClient.upload#bytebuf-long-int-filerangewritetype + } + + /** + * Generates a code sample for using {@link FileClient#uploadFromFile(String)} + */ + public void uploadFile() { + FileClient fileClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileClient.uploadFromFile#string + fileClient.uploadFromFile("someFilePath"); + // END: com.azure.storage.file.fileClient.uploadFromFile#string + } + + /** + * Generates a code sample for using {@link FileAsyncClient#uploadFromFile(String)} + */ + public void uploadFileAsync() { + FileAsyncClient fileAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileAsyncClient.uploadFromFile#string + fileAsyncClient.uploadFromFile("someFilePath").subscribe( + response -> { }, + error -> System.err.print(error.toString()), + () -> System.out.println("Complete deleting the file!") + ); + // END: com.azure.storage.file.fileAsyncClient.uploadFromFile#string + } + + /** + * Generates a code sample for using {@link FileClient#uploadFromFile(String, FileRangeWriteType)} + */ + public void uploadFileMaxOverload() { + FileClient fileClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileClient.uploadFromFile#string-filerangewritetype + fileClient.uploadFromFile("someFilePath", FileRangeWriteType.UPDATE); + if (fileClient.getProperties() != null) { + System.out.printf("Upload the file with length of %d completed", + fileClient.getProperties().value().contentLength()); + } + // END: com.azure.storage.file.fileClient.uploadFromFile#string-filerangewritetype + } + + /** + * Generates a code sample for using {@link FileAsyncClient#uploadFromFile(String, FileRangeWriteType)} + */ + public void uploadFileAsyncMaxOverload() { + FileAsyncClient fileAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileAsyncClient.uploadFromFile#string-filerangewritetype + fileAsyncClient.uploadFromFile("someFilePath", FileRangeWriteType.UPDATE) + .subscribe(response -> { + if (fileAsyncClient.getProperties() != null) { + System.out.printf("Upload the file with length of %d completed", + fileAsyncClient.getProperties().block().value().contentLength()); + } + }); + // END: com.azure.storage.file.fileAsyncClient.uploadFromFile#string-filerangewritetype + } + + /** + * Generates a code sample for using {@link FileClient#downloadWithProperties()} + */ + public void downloadData() { + FileClient fileClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileClient.downloadWithProperties + Response response = fileClient.downloadWithProperties(); + System.out.println("Complete downloading the data with status code: " + response.statusCode()); + response.value().body().subscribe( + byteBuf -> System.out.println("Complete downloading the data with body: " + + byteBuf.toString(StandardCharsets.UTF_8)), + error -> System.err.print(error.toString()), + () -> System.out.println("Complete downloading the data!") + ); + // END: com.azure.storage.file.fileClient.downloadWithProperties + } + + /** + * Generates a code sample for using {@link FileAsyncClient#downloadWithProperties()} + */ + public void downloadDataAsync() { + FileAsyncClient fileAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileAsyncClient.downloadWithProperties + fileAsyncClient.downloadWithProperties().subscribe( + response -> { }, + error -> System.err.print(error.toString()), + () -> System.out.println("Complete downloading the data!") + ); + // END: com.azure.storage.file.fileAsyncClient.downloadWithProperties + } + + /** + * Generates a code sample for using {@link FileClient#downloadWithProperties(FileRange, Boolean)} + */ + public void downloadDataMaxOverload() { + FileClient fileClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileClient.downloadWithProperties#filerange-boolean + Response response = fileClient.downloadWithProperties(new FileRange(1024, 2047L), + false); + System.out.println("Complete downloading the data with status code: " + response.statusCode()); + response.value().body().subscribe( + byteBuf -> System.out.println("Complete downloading the data with body: " + + byteBuf.toString(StandardCharsets.UTF_8)), + error -> System.err.print(error.toString()), + () -> System.out.println("Complete downloading the data!") + ); + // END: com.azure.storage.file.fileClient.downloadWithProperties#filerange-boolean + } + + /** + * Generates a code sample for using {@link FileAsyncClient#downloadWithProperties(FileRange, Boolean)} + */ + public void downloadDataAsyncMaxOverload() { + FileAsyncClient fileAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileAsyncClient.downloadWithProperties#filerange-boolean + fileAsyncClient.downloadWithProperties(new FileRange(1024, 2047L), false).subscribe( + response -> { }, + error -> System.err.print(error.toString()), + () -> System.out.println("Complete downloading the data!") + ); + // END: com.azure.storage.file.fileAsyncClient.downloadWithProperties#filerange-boolean + } + + /** + * Generates a code sample for using {@link FileClient#downloadToFile(String)} + */ + public void downloadFile() { + FileClient fileClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileClient.downloadToFile#string + fileClient.downloadToFile("somelocalfilepath"); + if (Files.exists(Paths.get("somelocalfilepath"))) { + System.out.println("Complete downloading the file."); + } + // END: com.azure.storage.file.fileClient.downloadToFile#string + } + + /** + * Generates a code sample for using {@link FileAsyncClient#downloadToFile(String)} + */ + public void downloadFileAsync() { + FileAsyncClient fileAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileAsyncClient.downloadToFile#string + fileAsyncClient.downloadToFile("somelocalfilepath").subscribe( + response -> { + if (Files.exists(Paths.get("somelocalfilepath"))) { + System.out.println("Successfully downloaded the file."); + } + }, + error -> System.err.print(error.toString()), + () -> System.out.println("Complete downloading the file!") + ); + // END: com.azure.storage.file.fileAsyncClient.downloadToFile#string + } + + /** + * Generates a code sample for using {@link FileClient#downloadToFile(String, FileRange)} + */ + public void downloadFileMaxOverload() { + FileClient fileClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileClient.downloadToFile#string-filerange + fileClient.downloadToFile("somelocalfilepath", new FileRange(1024, 2047L)); + if (Files.exists(Paths.get("somelocalfilepath"))) { + System.out.println("Complete downloading the file."); + } + // END: com.azure.storage.file.fileClient.downloadToFile#string-filerange + } + + /** + * Generates a code sample for using {@link FileAsyncClient#downloadToFile(String, FileRange)} + */ + public void downloadFileAsyncMaxOverload() { + FileAsyncClient fileAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileAsyncClient.downloadToFile#string-filerange + fileAsyncClient.downloadToFile("somelocalfilepath", new FileRange(1024, 2047L)).subscribe( + response -> { + if (Files.exists(Paths.get("somelocalfilepath"))) { + System.out.println("Successfully downloaded the file."); + } + }, + error -> System.err.print(error.toString()), + () -> System.out.println("Complete downloading the file!") + ); + // END: com.azure.storage.file.fileAsyncClient.downloadToFile#string-filerange + } + + /** + * Generates a code sample for using {@link FileClient#delete()} + */ + public void deleteFile() { + FileClient fileClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileClient.delete + VoidResponse response = fileClient.delete(); + System.out.println("Complete deleting the file with status code: " + response.statusCode()); + // END: com.azure.storage.file.fileClient.delete + } + + /** + * Generates a code sample for using {@link FileAsyncClient#delete()} + */ + public void deleteFileAsync() { + FileAsyncClient fileAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileAsyncClient.delete + fileAsyncClient.delete().subscribe( + response -> { }, + error -> System.err.print(error.toString()), + () -> System.out.println("Complete deleting the file!") + ); + // END: com.azure.storage.file.fileAsyncClient.delete + } + + /** + * Generates a code sample for using {@link FileClient#getProperties()} + */ + public void getProperties() { + FileClient fileClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileClient.getProperties + Response response = fileClient.getProperties(); + FileProperties properties = response.value(); + System.out.printf("File latest modified date is %s.", properties.lastModified()); + // END: com.azure.storage.file.fileClient.getProperties + } + + /** + * Generates a code sample for using {@link FileAsyncClient#getProperties()} + */ + public void getPropertiesAsync() { + FileAsyncClient fileAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileAsyncClient.getProperties + fileAsyncClient.getProperties() + .subscribe(response -> { + FileProperties properties = response.value(); + System.out.printf("File latest modified date is %s.", properties.lastModified()); + }); + // END: com.azure.storage.file.fileAsyncClient.getProperties + } + + /** + * Generates a code sample for using {@link FileClient#setMetadata(Map)} + */ + public void setMetadata() { + FileClient fileClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileClient.setMetadata#map + Response response = fileClient.setMetadata( + Collections.singletonMap("file", "updatedMetadata")); + System.out.printf("Setting the file metadata completed with status code %d", response.statusCode()); + // END: com.azure.storage.file.fileClient.setMetadata#map + } + + /** + * Generates a code sample for using {@link FileAsyncClient#setMetadata(Map)} + */ + public void setMetadataAsync() { + FileAsyncClient fileAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileAsyncClient.setMetadata#map + fileAsyncClient.setMetadata(Collections.singletonMap("file", "updatedMetadata")) + .subscribe(response -> System.out.printf("Setting the file metadata completed with status code %d", + response.statusCode())); + // END: com.azure.storage.file.fileAsyncClient.setMetadata#map + } + + /** + * Generates a code sample for using {@link FileClient#setMetadata(Map)} to clear metadata. + */ + public void clearMetadata() { + FileClient fileClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileClient.setMetadata#map.clearMetadata + Response response = fileClient.setMetadata(null); + System.out.printf("Setting the file metadata completed with status code %d", response.statusCode()); + // END: com.azure.storage.file.fileClient.setMetadata#map.clearMetadata + } + + /** + * Generates a code sample for using {@link FileAsyncClient#setMetadata(Map)} to clear metadata. + */ + public void clearMetadataAsync() { + FileAsyncClient fileAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileAsyncClient.setMetadata#map.clearMetadata + fileAsyncClient.setMetadata(null) + .subscribe(response -> System.out.printf("Setting the file metadata completed with status code %d", + response.statusCode())); + // END: com.azure.storage.file.fileAsyncClient.setMetadata#map.clearMetadata + } + + /** + * Generates a code sample for using {@link FileClient#setHttpHeaders(long, FileHTTPHeaders)} + */ + public void setHTTPHeaders() { + FileClient fileClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileClient.setHttpHeaders#long-filehttpheaders + FileHTTPHeaders httpHeaders = new FileHTTPHeaders().fileContentType("text/plain"); + Response response = fileClient.setHttpHeaders(1024, httpHeaders); + System.out.printf("Setting the file httpHeaders completed with status code %d", response.statusCode()); + // END: com.azure.storage.file.fileClient.setHttpHeaders#long-filehttpheaders + } + + /** + * Generates a code sample for using {@link FileAsyncClient#setHttpHeaders(long, FileHTTPHeaders)} + */ + public void setHTTPHeadersAsync() { + FileAsyncClient fileAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileAsyncClient.setHttpHeaders#long-filehttpheaders + FileHTTPHeaders httpHeaders = new FileHTTPHeaders().fileContentType("text/plain"); + fileAsyncClient.setHttpHeaders(1024, httpHeaders) + .subscribe(response -> System.out.printf("Setting the file httpHeaders completed with status code %d", + response.statusCode())); + // END: com.azure.storage.file.fileAsyncClient.setHttpHeaders#long-filehttpheaders + } + + /** + * Generates a code sample for using {@link FileClient#setHttpHeaders(long, FileHTTPHeaders)} to clear httpHeaders. + */ + public void clearHTTPHeaders() { + FileClient fileClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileClient.setHttpHeaders#long-filehttpheaders.clearHttpHeaders + Response response = fileClient.setHttpHeaders(1024, null); + System.out.printf("Setting the file httpHeaders completed with status code %d", response.statusCode()); + // END: com.azure.storage.file.fileClient.setHttpHeaders#long-filehttpheaders.clearHttpHeaders + } + + /** + * Generates a code sample for using {@link FileAsyncClient#setHttpHeaders(long, FileHTTPHeaders)} to clear httpHeaders. + */ + public void clearHTTPHeadersAsync() { + FileAsyncClient fileAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileAsyncClient.setHttpHeaders#long-filehttpheaders.clearHttpHeaders + fileAsyncClient.setHttpHeaders(1024, null) + .subscribe(response -> System.out.printf("Setting the file httpHeaders completed with status code %d", + response.statusCode())); + // END: com.azure.storage.file.fileAsyncClient.setHttpHeaders#long-filehttpheaders.clearHttpHeaders + } + + /** + * Generates a code sample for using {@link FileClient#listRanges()} + */ + public void listRanges() { + FileClient fileClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileClient.listRanges + Iterable ranges = fileClient.listRanges(); + ranges.forEach(range -> + System.out.printf("List ranges completed with start: %d, end: %d", range.start(), range.end())); + // END: com.azure.storage.file.fileClient.listRanges + } + + /** + * Generates a code sample for using {@link FileAsyncClient#listRanges()} + */ + public void listRangesAsync() { + FileAsyncClient fileAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileAsyncClient.listRanges + fileAsyncClient.listRanges().subscribe(range -> + System.out.printf("List ranges completed with start: %d, end: %d", range.start(), range.end())); + // END: com.azure.storage.file.fileAsyncClient.listRanges + } + /** + * Generates a code sample for using {@link FileClient#listRanges(FileRange)} + */ + public void listRangesMaxOverload() { + FileClient fileClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileClient.listRanges#filerange + Iterable ranges = fileClient.listRanges(new FileRange(1024, 2048L)); + ranges.forEach(range -> + System.out.printf("List ranges completed with start: %d, end: %d", range.start(), range.end())); + // END: com.azure.storage.file.fileClient.listRanges#filerange + } + + /** + * Generates a code sample for using {@link FileAsyncClient#listRanges(FileRange)} + */ + public void listRangesAsyncMaxOverload() { + FileAsyncClient fileAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileAsyncClient.listRanges#filerange + fileAsyncClient.listRanges(new FileRange(1024, 2048L)) + .subscribe(result -> System.out.printf("List ranges completed with start: %d, end: %d", + result.start(), result.end())); + // END: com.azure.storage.file.fileAsyncClient.listRanges#filerange + } + /** + * Generates a code sample for using {@link FileClient#listHandles()} + */ + public void listHandles() { + FileClient fileClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileClient.listHandles + fileClient.listHandles() + .forEach(handleItem -> System.out.printf("List handles completed with handleId %d", + handleItem.handleId())); + // END: com.azure.storage.file.fileClient.listHandles + } + + /** + * Generates a code sample for using {@link FileAsyncClient#listHandles()} + */ + public void listHandlesAsync() { + FileAsyncClient fileAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileAsyncClient.listHandles + fileAsyncClient.listHandles() + .subscribe(result -> System.out.printf("List handles completed with handle id %s", result.handleId())); + // END: com.azure.storage.file.fileAsyncClient.listHandles + } + /** + * Generates a code sample for using {@link FileClient#listHandles(Integer)} + */ + public void listHandlesWithOverload() { + FileClient fileClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileClient.listHandles#integer + fileClient.listHandles(10) + .forEach(handleItem -> System.out.printf("List handles completed with handleId %d", + handleItem.handleId())); + // END: com.azure.storage.file.fileClient.listHandles#integer + } + + /** + * Generates a code sample for using {@link FileAsyncClient#listHandles(Integer)} + */ + public void listHandlesAsyncMaxOverload() { + FileAsyncClient fileAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileAsyncClient.listHandles#integer + fileAsyncClient.listHandles(10) + .subscribe(result -> System.out.printf("List handles completed with handle id %s", result.handleId())); + // END: com.azure.storage.file.fileAsyncClient.listHandles#integer + } + /** + * Generates a code sample for using {@link FileClient#forceCloseHandles(String)} + */ + public void forceCloseHandles() { + FileClient fileClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileClient.forceCloseHandles#string + fileClient.listHandles(10) + .forEach(result -> + fileClient.forceCloseHandles(result.handleId()).forEach(numOfClosedHandles -> + System.out.printf("Close %d handles.", numOfClosedHandles) + )); + // END: com.azure.storage.file.fileClient.forceCloseHandles#string + } + + /** + * Generates a code sample for using {@link FileAsyncClient#forceCloseHandles(String)} + */ + public void forceCloseHandlesAsync() { + FileAsyncClient fileAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileAsyncClient.forceCloseHandles#string + fileAsyncClient.listHandles(10) + .subscribe(result -> { + fileAsyncClient.forceCloseHandles(result.handleId()).subscribe(numOfClosedHandles -> + System.out.printf("Close %d handles.", numOfClosedHandles)); + }); + // END: com.azure.storage.file.fileAsyncClient.forceCloseHandles#string + } + + /** + * Generates a code sample for using {@link FileClient#getShareSnapshotId()} + */ + public void getShareSnapshotId() { + // BEGIN: com.azure.storage.file.fileClient.getShareSnapshotId + OffsetDateTime currentTime = OffsetDateTime.of(LocalDateTime.now(), ZoneOffset.UTC); + FileClient fileClient = new FileClientBuilder() + .endpoint("https://${accountName}.file.core.windows.net") + .credential(SASTokenCredential.fromQuery("${SASToken}")) + .shareName("myshare") + .filePath("myfile") + .snapshot(currentTime.toString()) + .buildClient(); + fileClient.getShareSnapshotId(); + // END: com.azure.storage.file.fileClient.getShareSnapshotId + } + + /** + * Generates a code sample for using {@link FileAsyncClient#getShareSnapshotId()} + */ + public void getShareSnapshotIdAsync() { + // BEGIN: com.azure.storage.file.fileAsyncClient.getShareSnapshotId + OffsetDateTime currentTime = OffsetDateTime.of(LocalDateTime.now(), ZoneOffset.UTC); + FileAsyncClient fileAsyncClient = new FileClientBuilder() + .endpoint("https://${accountName}.file.core.windows.net") + .credential(SASTokenCredential.fromQuery("${SASToken}")) + .shareName("myshare") + .filePath("myfiile") + .snapshot(currentTime.toString()) + .buildAsyncClient(); + fileAsyncClient.getShareSnapshotId(); + // END: com.azure.storage.file.fileAsyncClient.getShareSnapshotId + } +} diff --git a/storage/client/file/src/samples/java/com/azure/storage/file/FileServiceJavaDocCodeSamples.java b/storage/client/file/src/samples/java/com/azure/storage/file/FileServiceJavaDocCodeSamples.java new file mode 100644 index 0000000000000..95e6971804713 --- /dev/null +++ b/storage/client/file/src/samples/java/com/azure/storage/file/FileServiceJavaDocCodeSamples.java @@ -0,0 +1,423 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.storage.file; + +import com.azure.core.http.rest.Response; +import com.azure.core.http.rest.VoidResponse; +import com.azure.storage.common.credentials.SASTokenCredential; +import com.azure.storage.common.credentials.SharedKeyCredential; +import com.azure.storage.file.models.FileServiceProperties; +import com.azure.storage.file.models.ListSharesOptions; +import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.util.Collections; +import java.util.Map; + +/** + * Contains code snippets when generating javadocs through doclets for {@link FileServiceClient} and {@link FileServiceAsyncClient}. + */ +public class FileServiceJavaDocCodeSamples { + /** + * Generates code sample for {@link FileServiceClient} instantiation. + */ + public void initialization() { + // BEGIN: com.azure.storage.file.fileServiceClient.instantiation + FileServiceClient client = new FileServiceClientBuilder() + .connectionString("${connectionString}") + .endpoint("${endpoint}") + .buildClient(); + // END: com.azure.storage.file.fileServiceClient.instantiation + } + + /** + * Generates code sample for {@link FileServiceAsyncClient} instantiation. + */ + public void asyncInitialization() { + // BEGIN: com.azure.storage.file.fileServiceAsyncClient.instantiation + ShareAsyncClient client = new ShareClientBuilder() + .connectionString("${connectionString}") + .endpoint("${endpoint}") + .buildAsyncClient(); + // END: com.azure.storage.file.fileServiceAsyncClient.instantiation + } + /** + * Generates code sample for creating a {@link FileServiceClient} with {@link SASTokenCredential} + * @return An instance of {@link FileServiceClient} + */ + public FileServiceClient createClientWithSASToken() { + // BEGIN: com.azure.storage.file.fileServiceClient.instantiation.sastoken + FileServiceClient fileServiceClient = new FileServiceClientBuilder() + .endpoint("https://${accountName}.file.core.windows.net?${SASToken}") + .buildClient(); + // END: com.azure.storage.file.fileServiceClient.instantiation.sastoken + return fileServiceClient; + } + + /** + * Generates code sample for creating a {@link FileServiceAsyncClient} with {@link SASTokenCredential} + * @return An instance of {@link FileServiceAsyncClient} + */ + public FileServiceAsyncClient createAsyncClientWithSASToken() { + // BEGIN: com.azure.storage.file.fileServiceAsyncClient.instantiation.sastoken + FileServiceAsyncClient fileServiceAsyncClient = new FileServiceClientBuilder() + .endpoint("https://{accountName}.file.core.windows.net?{SASToken}") + .buildAsyncClient(); + // END: com.azure.storage.file.fileServiceAsyncClient.instantiation.sastoken + return fileServiceAsyncClient; + } + + /** + * Generates code sample for creating a {@link FileServiceClient} with {@link SASTokenCredential} + * {@code SASTokenQueryParams} is composed of the Key + * @return An instance of {@link FileServiceClient} + */ + public FileServiceClient createClientWithCredential() { + // BEGIN: com.azure.storage.file.fileServiceClient.instantiation.credential + FileServiceClient fileServiceClient = new FileServiceClientBuilder() + .endpoint("https://{accountName}.file.core.windows.net") + .credential(SASTokenCredential.fromQuery("${SASTokenQueryParams}")) + .buildClient(); + // END: com.azure.storage.file.fileServiceClient.instantiation.credential + return fileServiceClient; + } + + /** + * Generates code sample for creating a {@link FileServiceAsyncClient} with {@link SASTokenCredential} + * @return An instance of {@link FileServiceAsyncClient} + */ + public FileServiceAsyncClient createAsyncClientWithCredential() { + // BEGIN: com.azure.storage.file.fileServiceAsyncClient.instantiation.credential + FileServiceAsyncClient fileServiceAsyncClient = new FileServiceClientBuilder() + .endpoint("https://{accountName}.file.core.windows.net") + .credential(SASTokenCredential.fromQuery("${SASTokenQueryParams}")) + .buildAsyncClient(); + // END: com.azure.storage.file.fileServiceAsyncClient.instantiation.credential + return fileServiceAsyncClient; + } + + /** + * Generates code sample for creating a {@link FileServiceClient} with {@code connectionString} which turns into {@link SharedKeyCredential} + * @return An instance of {@link FileServiceClient} + */ + public FileServiceClient createClientWithConnectionString() { + // BEGIN: com.azure.storage.file.fileServiceClient.instantiation.connectionstring + String connectionString = "DefaultEndpointsProtocol=https;AccountName={name};AccountKey={key};" + + "EndpointSuffix={core.windows.net}"; + FileServiceClient fileServiceClient = new FileServiceClientBuilder() + .connectionString(connectionString) + .buildClient(); + // END: com.azure.storage.file.fileServiceClient.instantiation.connectionstring + return fileServiceClient; + } + + /** + * Generates code sample for creating a {@link FileServiceAsyncClient} with {@code connectionString} which turns into {@link SharedKeyCredential} + * @return An instance of {@link FileServiceAsyncClient} + */ + public FileServiceAsyncClient createAsyncClientWithConnectionString() { + // BEGIN: com.azure.storage.file.fileServiceAsyncClient.instantiation.connectionstring + String connectionString = "DefaultEndpointsProtocol=https;AccountName={name};AccountKey={key};" + + "EndpointSuffix={core.windows.net}"; + FileServiceAsyncClient fileServiceAsyncClient = new FileServiceClientBuilder() + .connectionString(connectionString) + .buildAsyncClient(); + // END: com.azure.storage.file.fileServiceAsyncClient.instantiation.connectionstring + return fileServiceAsyncClient; + } + + /** + * Generates a code sample for using {@link FileServiceClient#createShare(String)} + */ + public void createShare() { + FileServiceClient fileServiceClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileServiceClient.createShare#string + Response response = fileServiceClient.createShare("myshare"); + System.out.printf("Creating the share completed with status code %d", response.statusCode()); + // END: com.azure.storage.file.fileServiceClient.createShare#string + } + + /** + * Generates a code sample for using {@link FileServiceAsyncClient#createShare(String)} + */ + public void createShareAsync() { + FileServiceAsyncClient fileServiceAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileServiceAsyncClient.createShare#string + fileServiceAsyncClient.createShare("myshare").subscribe( + response -> { }, + error -> System.err.print(error.toString()), + () -> System.out.println("Complete creating the share!") + ); + // END: com.azure.storage.file.fileServiceAsyncClient.createShare#string + } + + /** + * Generates a code sample for using {@link FileServiceClient#createShare(String, Map, Integer)} with metadata + */ + public void createShareWithMetadata() { + FileServiceClient fileServiceClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileServiceClient.createShare#string-map-integer.metadata + Response response = fileServiceClient.createShare("test", + Collections.singletonMap("share", "metadata"), null); + System.out.printf("Creating the share completed with status code %d", response.statusCode()); + // END: com.azure.storage.file.fileServiceClient.createShare#string-map-integer.metadata + } + + /** + * Generates a code sample for using {@link FileServiceAsyncClient#createShare(String, Map, Integer)} with metadata + */ + public void createShareAsyncWithMetadata() { + FileServiceAsyncClient fileServiceAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileServiceAsyncClient.createShare#string-map-integer.metadata + fileServiceAsyncClient.createShare("test", Collections.singletonMap("share", "metadata"), null) + .subscribe( + response -> System.out.printf("Creating the share completed with status code %d", response.statusCode()), + error -> System.err.print(error.toString()), + () -> System.out.println("Complete creating the share!") + ); + // END: com.azure.storage.file.fileServiceAsyncClient.createShare#string-map-integer.metadata + } + + /** + * Generates a code sample for using {@link FileServiceClient#createShare(String, Map, Integer)} with quota. + */ + public void createShareWithQuota() { + FileServiceClient fileServiceClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileServiceClient.createShare#string-map-integer.quota + Response response = fileServiceClient.createShare("test", null, 10); + System.out.printf("Creating the share completed with status code %d", response.statusCode()); + // END: com.azure.storage.file.fileServiceClient.createShare#string-map-integer.quota + } + + /** + * Generates a code sample for using {@link FileServiceAsyncClient#createShare(String, Map, Integer)} with quota. + */ + public void createShareAsyncWithQuota() { + FileServiceAsyncClient fileServiceAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileServiceAsyncClient.createShare#string-map-integer.quota + fileServiceAsyncClient.createShare("test", null, 10) + .subscribe( + response -> System.out.printf("Creating the share completed with status code %d", + response.statusCode()), + error -> System.err.print(error.toString()), + () -> System.out.println("Complete creating the share!") + ); + // END: com.azure.storage.file.fileServiceAsyncClient.createShare#string-map-integer.quota + } + + /** + * Generates a code sample for using {@link FileServiceClient#listShares()} + */ + public void listShares() { + FileServiceClient fileServiceClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileServiceClient.listShares + fileServiceClient.listShares().forEach( + shareItem -> System.out.printf("Share %s exists in the account", shareItem.name()) + ); + // END: com.azure.storage.file.fileServiceClient.listShares + } + + /** + * Generates a code sample for using {@link FileServiceAsyncClient#listShares()} + */ + public void listSharesAsync() { + FileServiceAsyncClient fileServiceAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileServiceAsyncClient.listShares + fileServiceAsyncClient.listShares().subscribe( + shareItem -> System.out.printf("Share %s exists in the account", shareItem.name()), + error -> System.err.print(error.toString()), + () -> System.out.println("Complete listing the shares!") + ); + // END: com.azure.storage.file.fileServiceAsyncClient.listShares + } + + /** + * Generates a code sample for using {@link FileServiceClient#listShares(ListSharesOptions)} of prefix. + */ + public void listSharesWithPrefix() { + FileServiceClient fileServiceClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileServiceClient.listShares#ListSharesOptions.prefix + fileServiceClient.listShares(new ListSharesOptions().prefix("azure")).forEach( + shareItem -> System.out.printf("Share %s exists in the account", shareItem.name()) + ); + // END: com.azure.storage.file.fileServiceClient.listShares#ListSharesOptions.prefix + } + + /** + * Generates a code sample for using {@link FileServiceAsyncClient#listShares(ListSharesOptions)} of prefix. + */ + public void listSharesAsyncWithPrefix() { + FileServiceAsyncClient fileServiceAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileServiceAsyncClient.listShares#ListSharesOptions.prefix + fileServiceAsyncClient.listShares(new ListSharesOptions().prefix("azure")).subscribe( + shareItem -> System.out.printf("Share %s exists in the account", shareItem.name()), + error -> System.err.print(error.toString()), + () -> System.out.println("Complete listing the shares!") + ); + // END: com.azure.storage.file.fileServiceAsyncClient.listShares#ListSharesOptions.prefix + } + + /** + * Generates a code sample for using {@link FileServiceClient#listShares(ListSharesOptions)} of metadata and snapshot. + */ + public void listSharesWithMetadataAndSnapshot() { + FileServiceClient fileServiceClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileServiceClient.listShares#ListSharesOptions.metadata.snapshot + fileServiceClient.listShares(new ListSharesOptions().includeMetadata(true) + .includeSnapshots(true)).forEach( + shareItem -> System.out.printf("Share %s exists in the account", shareItem.name()) + ); + // END: com.azure.storage.file.fileServiceClient.listShares#ListSharesOptions.metadata.snapshot + } + + /** + * Generates a code sample for using {@link FileServiceAsyncClient#listShares(ListSharesOptions)} of metadata and snapshot. + */ + public void listSharesAsyncWithOverload() { + FileServiceAsyncClient fileServiceAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileServiceAsyncClient.listShares#ListSharesOptions.metadata.snapshot + fileServiceAsyncClient.listShares(new ListSharesOptions().includeMetadata(true) + .includeSnapshots(true)).subscribe( + shareItem -> System.out.printf("Share %s exists in the account", shareItem.name()), + error -> System.err.print(error.toString()), + () -> System.out.println("Complete listing the shares!") + ); + // END: com.azure.storage.file.fileServiceAsyncClient.listShares#ListSharesOptions.metadata.snapshot + } + + /** + * Generates a code sample for using {@link FileServiceClient#deleteShare(String)} + */ + public void deleteShare() { + FileServiceClient fileServiceClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileServiceClient.deleteShare#string + fileServiceClient.deleteShare("myshare"); + // END: com.azure.storage.file.fileServiceClient.deleteShare#string + } + + /** + * Generates a code sample for using {@link FileServiceAsyncClient#deleteShare(String)} + */ + public void deleteShareAsync() { + FileServiceAsyncClient fileServiceAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileServiceAsyncClient.deleteShare#string + fileServiceAsyncClient.deleteShare("test").subscribe( + response -> System.out.println("Deleting the share completed with status code: " + response.statusCode()) + ); + // END: com.azure.storage.file.fileServiceAsyncClient.deleteShare#string + } + + /** + * Generates a code sample for using {@link FileServiceClient#deleteShare(String, String)} + */ + public void deleteShareMaxOverload() { + FileServiceClient fileServiceClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileServiceClient.deleteShare#string-string + OffsetDateTime midnight = OffsetDateTime.of(LocalDateTime.now(), ZoneOffset.UTC); + VoidResponse response = fileServiceClient.deleteShare("test", midnight.toString()); + System.out.printf("Deleting the snapshot completed with status code %d", response.statusCode()); + // END: com.azure.storage.file.fileServiceClient.deleteShare#string-string + } + + /** + * Generates a code sample for using {@link FileServiceAsyncClient#deleteShare(String, String)} + */ + public void deleteShareAsyncMaxOverload() { + FileServiceAsyncClient fileServiceAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileServiceAsyncClient.deleteShare#string-string + OffsetDateTime midnight = OffsetDateTime.of(LocalDateTime.now(), ZoneOffset.UTC); + fileServiceAsyncClient.deleteShare("test", midnight.toString()) + .subscribe(response -> System.out.printf("Deleting the snapshot completed with status code %d", + response.statusCode())); + // END: com.azure.storage.file.fileServiceAsyncClient.deleteShare#string-string + } + + /** + * Generates a code sample for using {@link FileServiceClient#getProperties()} + */ + public void getProperties() { + FileServiceClient fileServiceClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileServiceClient.getProperties + FileServiceProperties properties = fileServiceClient.getProperties().value(); + System.out.printf("Hour metrics enabled: %b, Minute metrics enabled: %b", properties.hourMetrics().enabled(), + properties.minuteMetrics().enabled()); + // END: com.azure.storage.file.fileServiceClient.getProperties + } + + /** + * Generates a code sample for using {@link FileServiceAsyncClient#getProperties()} + */ + public void getPropertiesAsync() { + FileServiceAsyncClient fileServiceAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileServiceAsyncClient.getProperties + fileServiceAsyncClient.getProperties() + .subscribe(response -> { + FileServiceProperties properties = response.value(); + System.out.printf("Hour metrics enabled: %b, Minute metrics enabled: %b", + properties.hourMetrics().enabled(), properties.minuteMetrics().enabled()); + }); + // END: com.azure.storage.file.fileServiceAsyncClient.getProperties + } + + /** + * Generates a code sample for using {@link FileServiceClient#setProperties(FileServiceProperties)} + */ + public void setProperties() { + FileServiceClient fileServiceClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileServiceClient.setProperties#fileServiceProperties + FileServiceProperties properties = fileServiceClient.getProperties().value(); + + properties.minuteMetrics().enabled(true); + properties.hourMetrics().enabled(true); + + VoidResponse response = fileServiceClient.setProperties(properties); + System.out.printf("Setting File service properties completed with status code %d", response.statusCode()); + // END: com.azure.storage.file.fileServiceClient.setProperties#fileServiceProperties + } + + /** + * Generates a code sample for using {@link FileServiceAsyncClient#setProperties(FileServiceProperties)} + */ + public void setPropertiesAsync() { + FileServiceAsyncClient fileServiceAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileServiceAsyncClient.setProperties#fileServiceProperties + FileServiceProperties properties = fileServiceAsyncClient.getProperties().block().value(); + + properties.minuteMetrics().enabled(true); + properties.hourMetrics().enabled(true); + + fileServiceAsyncClient.setProperties(properties) + .subscribe(response -> System.out.printf("Setting File service properties completed with status code %d", + response.statusCode())); + // END: com.azure.storage.file.fileServiceAsyncClient.setProperties#fileServiceProperties + } + + /** + * Generates a code sample for using {@link FileServiceClient#setProperties(FileServiceProperties)} to clear CORS in file service. + */ + public void clearProperties() { + FileServiceClient fileServiceClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileServiceClient.setProperties#fileServiceProperties.clearCORS + FileServiceProperties properties = fileServiceClient.getProperties().value(); + properties.cors(Collections.emptyList()); + + VoidResponse response = fileServiceClient.setProperties(properties); + System.out.printf("Setting File service properties completed with status code %d", response.statusCode()); + // END: com.azure.storage.file.fileServiceClient.setProperties#fileServiceProperties.clearCORS + } + + /** + * Generates a code sample for using {@link FileServiceAsyncClient#setProperties(FileServiceProperties)} to clear CORS in file service. + */ + public void clearPropertiesAsync() { + FileServiceAsyncClient fileServiceAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.fileServiceAsyncClient.setProperties#fileServiceProperties.clearCORS + FileServiceProperties properties = fileServiceAsyncClient.getProperties().block().value(); + properties.cors(Collections.emptyList()); + + fileServiceAsyncClient.setProperties(properties) + .subscribe(response -> System.out.printf("Setting File service properties completed with status code %d", + response.statusCode())); + // END: com.azure.storage.file.fileServiceAsyncClient.setProperties#fileServiceProperties.clearCORS + } +} diff --git a/storage/client/file/src/samples/java/com/azure/storage/file/ShareJavaDocCodeSamples.java b/storage/client/file/src/samples/java/com/azure/storage/file/ShareJavaDocCodeSamples.java new file mode 100644 index 0000000000000..01730abaf94a7 --- /dev/null +++ b/storage/client/file/src/samples/java/com/azure/storage/file/ShareJavaDocCodeSamples.java @@ -0,0 +1,580 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.storage.file; + +import com.azure.core.http.rest.Response; +import com.azure.core.http.rest.VoidResponse; +import com.azure.storage.common.credentials.SASTokenCredential; +import com.azure.storage.common.credentials.SharedKeyCredential; +import com.azure.storage.file.models.AccessPolicy; +import com.azure.storage.file.models.ShareInfo; +import com.azure.storage.file.models.ShareProperties; +import com.azure.storage.file.models.ShareSnapshotInfo; +import com.azure.storage.file.models.ShareStatistics; +import com.azure.storage.file.models.SignedIdentifier; +import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * Contains code snippets when generating javadocs through doclets for {@link ShareClient} and {@link ShareAsyncClient}. + */ +public class ShareJavaDocCodeSamples { + /** + * Generates code sample for {@link ShareClient} instantiation. + */ + public void initialization() { + // BEGIN: com.azure.storage.file.shareClient.instantiation + ShareClient client = new ShareClientBuilder() + .connectionString("${connectionString}") + .endpoint("${endpoint}") + .buildClient(); + // END: com.azure.storage.file.shareClient.instantiation + } + + /** + * Generates code sample for {@link ShareAsyncClient} instantiation. + */ + public void asyncInitialization() { + // BEGIN: com.azure.storage.file.shareAsyncClient.instantiation + ShareAsyncClient client = new ShareClientBuilder() + .connectionString("${connectionString}") + .endpoint("${endpoint}") + .buildAsyncClient(); + // END: com.azure.storage.file.shareAsyncClient.instantiation + } + + /** + * Generates code sample for creating a {@link ShareClient} with {@link SASTokenCredential} + * @return An instance of {@link ShareClient} + */ + public ShareClient createClientWithSASToken() { + + // BEGIN: com.azure.storage.file.shareClient.instantiation.sastoken + ShareClient shareClient = new ShareClientBuilder() + .endpoint("https://${accountName}.file.core.windows.net?${SASToken}") + .shareName("myshare") + .buildClient(); + // END: com.azure.storage.file.shareClient.instantiation.sastoken + return shareClient; + } + + /** + * Generates code sample for creating a {@link ShareAsyncClient} with {@link SASTokenCredential} + * @return An instance of {@link ShareAsyncClient} + */ + public ShareAsyncClient createAsyncClientWithSASToken() { + // BEGIN: com.azure.storage.file.shareAsyncClient.instantiation.sastoken + ShareAsyncClient shareAsyncClient = new ShareClientBuilder() + .endpoint("https://{accountName}.file.core.windows.net?{SASToken}") + .shareName("myshare") + .buildAsyncClient(); + // END: com.azure.storage.file.shareAsyncClient.instantiation.sastoken + return shareAsyncClient; + } + + /** + * Generates code sample for creating a {@link ShareClient} with {@link SASTokenCredential} + * @return An instance of {@link ShareClient} + */ + public ShareClient createClientWithCredential() { + + // BEGIN: com.azure.storage.file.shareClient.instantiation.credential + ShareClient shareClient = new ShareClientBuilder() + .endpoint("https://${accountName}.file.core.windows.net") + .credential(SASTokenCredential.fromQuery("${SASTokenQueryParams}")) + .shareName("myshare") + .buildClient(); + // END: com.azure.storage.file.shareClient.instantiation.credential + return shareClient; + } + + /** + * Generates code sample for creating a {@link ShareAsyncClient} with {@link SASTokenCredential} + * @return An instance of {@link ShareAsyncClient} + */ + public ShareAsyncClient createAsyncClientWithCredential() { + // BEGIN: com.azure.storage.file.shareAsyncClient.instantiation.credential + ShareAsyncClient shareAsyncClient = new ShareClientBuilder() + .endpoint("https://{accountName}.file.core.windows.net") + .credential(SASTokenCredential.fromQuery("${SASTokenQueryParams}")) + .shareName("myshare") + .buildAsyncClient(); + // END: com.azure.storage.file.shareAsyncClient.instantiation.credential + return shareAsyncClient; + } + + /** + * Generates code sample for creating a {@link ShareClient} with {@code connectionString} which turns into {@link SharedKeyCredential} + * @return An instance of {@link ShareClient} + */ + public ShareClient createClientWithConnectionString() { + // BEGIN: com.azure.storage.file.shareClient.instantiation.connectionstring + String connectionString = "DefaultEndpointsProtocol=https;AccountName={name};AccountKey={key};" + + "EndpointSuffix={core.windows.net}"; + ShareClient shareClient = new ShareClientBuilder() + .connectionString(connectionString).shareName("myshare") + .buildClient(); + // END: com.azure.storage.file.shareClient.instantiation.connectionstring + return shareClient; + } + + /** + * Generates code sample for creating a {@link ShareAsyncClient} with {@code connectionString} which turns into {@link SharedKeyCredential} + * @return An instance of {@link ShareAsyncClient} + */ + public ShareAsyncClient createAsyncClientWithConnectionString() { + // BEGIN: com.azure.storage.file.shareAsyncClient.instantiation.connectionstring + String connectionString = "DefaultEndpointsProtocol=https;AccountName={name};AccountKey={key};" + + "EndpointSuffix={core.windows.net}"; + ShareAsyncClient shareAsyncClient = new ShareClientBuilder() + .connectionString(connectionString).shareName("myshare") + .buildAsyncClient(); + // END: com.azure.storage.file.shareAsyncClient.instantiation.connectionstring + return shareAsyncClient; + } + + /** + * Generates a code sample for using {@link ShareClient#create()} + */ + public void createShare() { + ShareClient shareClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.shareClient.create + Response response = shareClient.create(); + System.out.println("Complete creating the shares with status code: " + response.statusCode()); + // END: com.azure.storage.file.shareClient.create + } + + /** + * Generates a code sample for using {@link ShareAsyncClient#create} + */ + public void createShareAsync() { + ShareAsyncClient shareAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.shareAsyncClient.create + shareAsyncClient.create().subscribe( + response -> { }, + error -> System.err.print(error.toString()), + () -> System.out.println("Complete creating the share!") + ); + // END: com.azure.storage.file.shareAsyncClient.create + } + + /** + * Generates a code sample for using {@link ShareClient#create(Map, Integer)} with Metadata. + */ + public void createShareMaxOverloadMetadata() { + ShareClient shareClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.shareClient.create#map-integer.metadata + Response response = shareClient.create(Collections.singletonMap("share", "metadata"), null); + System.out.println("Complete creating the shares with status code: " + response.statusCode()); + // END: com.azure.storage.file.shareClient.create#map-integer.metadata + } + + /** + * Generates a code sample for using {@link ShareAsyncClient#create(Map, Integer)} with Metadata. + */ + public void createShareAsyncMaxOverloadMetadata() { + ShareAsyncClient shareAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.shareAsyncClient.create#map-integer.metadata + shareAsyncClient.create(Collections.singletonMap("share", "metadata"), null).subscribe( + response -> System.out.printf("Creating the share completed with status code %d", response.statusCode()), + error -> System.err.print(error.toString()), + () -> System.out.println("Complete creating the share!") + ); + // END: com.azure.storage.file.shareAsyncClient.create#map-integer.metadata + } + + /** + * Generates a code sample for using {@link ShareClient#create(Map, Integer)} with Quota. + */ + public void createShareMaxOverloadQuota() { + ShareClient shareClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.shareClient.create#map-integer.quota + Response response = shareClient.create(null, 10); + System.out.println("Complete creating the shares with status code: " + response.statusCode()); + // END: com.azure.storage.file.shareClient.create#map-integer.quota + } + + /** + * Generates a code sample for using {@link ShareAsyncClient#create(Map, Integer)} with Quota. + */ + public void createShareAsyncMaxOverloadQuota() { + ShareAsyncClient shareAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.shareAsyncClient.create#map-integer.quota + shareAsyncClient.create(null, 10).subscribe( + response -> System.out.printf("Creating the share completed with status code %d", response.statusCode()), + error -> System.err.print(error.toString()), + () -> System.out.println("Complete creating the share!") + ); + // END: com.azure.storage.file.shareAsyncClient.create#map-integer.quota + } + /** + * Generates a code sample for using {@link ShareClient#createDirectory(String)} ()} + */ + public void createDirectory() { + ShareClient shareClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.shareClient.createDirectory#string + Response response = shareClient.createDirectory("mydirectory"); + System.out.println("Complete creating the directory with status code: " + response.statusCode()); + // END: com.azure.storage.file.shareClient.createDirectory#string + } + + /** + * Generates a code sample for using {@link ShareAsyncClient#createDirectory(String)} + */ + public void createDirectoryAsync() { + ShareAsyncClient shareAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.shareAsyncClient.createDirectory#string + shareAsyncClient.createDirectory("mydirectory").subscribe( + response -> { }, + error -> System.err.print(error.toString()), + () -> System.out.println("Complete creating the directory!") + ); + // END: com.azure.storage.file.shareAsyncClient.createDirectory#string + } + + /** + * Generates a code sample for using {@link ShareClient#createSnapshot()()} + */ + public void createSnapshot() { + ShareClient shareClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.shareClient.createSnapshot + Response response = shareClient.createSnapshot(); + System.out.println("Complete creating the share snpashot with snapshot id: " + response.value().snapshot()); + // END: com.azure.storage.file.shareClient.createSnapshot + } + + /** + * Generates a code sample for using {@link ShareAsyncClient#createSnapshot()} + */ + public void createSnapshotAsync() { + ShareAsyncClient shareAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.shareAsyncClient.createSnapshot + shareAsyncClient.createSnapshot().subscribe( + response -> System.out.println("Successfully creating the share snapshot with snapshot id: " + + response.value().snapshot()), + error -> System.err.println(error.toString()), + () -> System.out.println("Complete creating the share snapshot.") + ); + // END: com.azure.storage.file.shareAsyncClient.createSnapshot + } + + /** + * Generates a code sample for using {@link ShareClient#createSnapshot(Map)} + */ + public void createSnapshotWithMetadata() { + ShareClient shareClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.shareClient.createSnapshot#map + Response response = + shareClient.createSnapshot(Collections.singletonMap("snpashot", "metadata")); + System.out.println("Complete creating the share snpashot with snapshot id: " + response.value().snapshot()); + // END: com.azure.storage.file.shareClient.createSnapshot#map + } + + /** + * Generates a code sample for using {@link ShareAsyncClient#createSnapshot(Map)} + */ + public void createSnapshotAsyncWithMetadata() { + ShareAsyncClient shareAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.shareAsyncClient.createSnapshot#map + shareAsyncClient.createSnapshot(Collections.singletonMap("snapshot", "metadata")).subscribe( + response -> System.out.println("Successfully creating the share snapshot with snapshot id: " + + response.value().snapshot()), + error -> System.err.println(error.toString()), + () -> System.out.println("Complete creating the share snapshot.") + ); + // END: com.azure.storage.file.shareAsyncClient.createSnapshot#map + } + + /** + * Generates a code sample for using {@link ShareClient#createDirectory(String, Map)} + */ + public void createDirectoryMaxOverload() { + ShareClient shareClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.shareClient.createDirectory#string-map + Response response = shareClient.createDirectory("documents", + Collections.singletonMap("directory", "metadata")); + System.out.printf("Creating the directory completed with status code %d", response.statusCode()); + // END: com.azure.storage.file.shareClient.createDirectory#string-map + } + + /** + * Generates a code sample for using {@link ShareAsyncClient#createDirectory(String, Map)} + */ + public void createDirectoryAsyncMaxOverload() { + ShareAsyncClient shareAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.shareAsyncClient.createDirectory#string-map + shareAsyncClient.createDirectory("documents", Collections.singletonMap("directory", "metadata")) + .subscribe(response -> System.out.printf("Creating the directory completed with status code %d", + response.statusCode())); + // END: com.azure.storage.file.shareAsyncClient.createDirectory#string-map + } + + /** + * Generates a code sample for using {@link ShareClient#deleteDirectory(String)()} + */ + public void deleteDirectory() { + ShareClient shareClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.shareClient.deleteDirectory#string + VoidResponse response = shareClient.deleteDirectory("mydirectory"); + System.out.println("Complete deleting the directory with status code: " + response.statusCode()); + // END: com.azure.storage.file.shareClient.deleteDirectory#string + } + + /** + * Generates a code sample for using {@link ShareAsyncClient#deleteDirectory(String)()} + */ + public void deleteDirectoryAsync() { + ShareAsyncClient shareAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.shareAsyncClient.deleteDirectory#string + shareAsyncClient.deleteDirectory("mydirectory").subscribe( + response -> { }, + error -> System.err.println(error.toString()), + () -> System.out.println("Complete deleting the directory.") + ); + // END: com.azure.storage.file.shareAsyncClient.deleteDirectory#string + } + + /** + * Generates a code sample for using {@link ShareClient#delete} + */ + public void deleteShare() { + ShareClient shareClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.shareClient.delete + VoidResponse response = shareClient.delete(); + System.out.println("Complete deleting the share with status code: " + response.statusCode()); + // END: com.azure.storage.file.shareClient.delete + } + + + /** + * Generates a code sample for using {@link ShareAsyncClient#delete} + */ + public void deleteShareAsync() { + ShareAsyncClient shareAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.shareAsyncClient.delete + shareAsyncClient.delete().subscribe( + response -> System.out.println("Deleting the shareAsyncClient completed with status code: " + + response.statusCode()), + error -> System.err.println(error.toString()), + () -> System.out.println("Complete deleting the share.") + ); + // END: com.azure.storage.file.shareAsyncClient.delete + } + + /** + * Generates a code sample for using {@link ShareClient#getProperties()} + */ + public void getProperties() { + ShareClient shareClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.shareClient.getProperties + ShareProperties properties = shareClient.getProperties().value(); + System.out.printf("Share quota: %d, Metadata: %s", properties.quota(), properties.metadata()); + // END: com.azure.storage.file.shareClient.getProperties + } + + + /** + * Generates a code sample for using {@link ShareAsyncClient#getProperties()} + */ + public void getPropertiesAsync() { + ShareAsyncClient shareAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.shareAsyncClient.getProperties + shareAsyncClient.getProperties() + .subscribe(response -> { + ShareProperties properties = response.value(); + System.out.printf("Share quota: %d, Metadata: %s", properties.quota(), properties.metadata()); + }); + // END: com.azure.storage.file.shareAsyncClient.getProperties + } + + /** + * Generates a code sample for using {@link ShareClient#setQuota(int)} + */ + public void setQuota() { + ShareClient shareClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.shareClient.setQuota + Response response = shareClient.setQuota(1024); + System.out.printf("Setting the share quota completed with status code %d", response.statusCode()); + // END: com.azure.storage.file.shareClient.setQuota + } + + + /** + * Generates a code sample for using {@link ShareAsyncClient#setQuota(int)} + */ + public void setQuotaAsync() { + ShareAsyncClient shareAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.shareAsyncClient.setQuota + shareAsyncClient.setQuota(1024) + .subscribe(response -> + System.out.printf("Setting the share quota completed with status code %d", response.statusCode()) + ); + // END: com.azure.storage.file.shareAsyncClient.setQuota + } + + /** + * Generates a code sample for using {@link ShareClient#setMetadata(Map)} + */ + public void setMetadata() { + ShareClient shareClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.shareClient.setMetadata#map + Response response = shareClient.setMetadata(Collections.singletonMap("share", "updatedMetadata")); + System.out.printf("Setting the share metadata completed with status code %d", response.statusCode()); + // END: com.azure.storage.file.shareClient.setMetadata#map + } + + + /** + * Generates a code sample for using {@link ShareAsyncClient#setMetadata(Map)} + */ + public void setMetadataAsync() { + ShareAsyncClient shareAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.shareAsyncClient.setMetadata#map + shareAsyncClient.setMetadata(Collections.singletonMap("share", "updatedMetadata")) + .subscribe(response -> + System.out.printf("Setting the share metadata completed with status code %d", response.statusCode()) + ); + // END: com.azure.storage.file.shareAsyncClient.setMetadata#map + } + + /** + * Generates a code sample for using {@link ShareClient#setMetadata(Map)} to clear the metadata. + */ + public void clearMetadata() { + ShareClient shareClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.shareClient.clearMetadata#map + Response response = shareClient.setMetadata(null); + System.out.printf("Setting the share metadata completed with status code %d", response.statusCode()); + // END: com.azure.storage.file.shareClient.clearMetadata#map + } + + + /** + * Generates a code sample for using {@link ShareAsyncClient#setMetadata(Map)} to clear the metadata. + */ + public void clearMetadataAsync() { + ShareAsyncClient shareAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.shareAsyncClient.clearMetadata#map + shareAsyncClient.setMetadata(null) + .subscribe(response -> + System.out.printf("Setting the share metadata completed with status code %d", response.statusCode()) + ); + // END: com.azure.storage.file.shareAsyncClient.clearMetadata#map + } + + /** + * Generates a code sample for using {@link ShareClient#getAccessPolicy()} + */ + public void getAccessPolicy() { + ShareClient shareClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.shareClient.getAccessPolicy + for (SignedIdentifier result : shareClient.getAccessPolicy()) { + System.out.printf("Access policy %s allows these permissions: %s", result.id(), result.accessPolicy().permission()); + } + // END: com.azure.storage.file.shareClient.getAccessPolicy + } + + /** + * Generates a code sample for using {@link ShareAsyncClient#getAccessPolicy()} + */ + public void getAccessPolicyAsync() { + ShareAsyncClient shareAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.shareAsyncClient.getAccessPolicy + shareAsyncClient.getAccessPolicy() + .subscribe(result -> System.out.printf("Access policy %s allows these permissions: %s", result.id(), + result.accessPolicy().permission()) + ); + // END: com.azure.storage.file.shareAsyncClient.getAccessPolicy + } + + /** + * Generates a code sample for using {@link ShareClient#setAccessPolicy(List)} + */ + public void setAccessPolicy() { + ShareClient shareClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.shareClient.setAccessPolicy + AccessPolicy accessPolicy = new AccessPolicy().permission("r") + .start(OffsetDateTime.now(ZoneOffset.UTC)) + .expiry(OffsetDateTime.now(ZoneOffset.UTC).plusDays(10)); + + SignedIdentifier permission = new SignedIdentifier().id("mypolicy").accessPolicy(accessPolicy); + + Response response = shareClient.setAccessPolicy(Collections.singletonList(permission)); + System.out.printf("Setting access policies completed with status code %d", response.statusCode()); + // END: com.azure.storage.file.shareClient.setAccessPolicy + } + + /** + * Generates a code sample for using {@link ShareAsyncClient#setAccessPolicy(List)} + */ + public void setAccessPolicyAsync() { + ShareAsyncClient shareAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.shareAsyncClient.setAccessPolicy + AccessPolicy accessPolicy = new AccessPolicy().permission("r") + .start(OffsetDateTime.now(ZoneOffset.UTC)) + .expiry(OffsetDateTime.now(ZoneOffset.UTC).plusDays(10)); + + SignedIdentifier permission = new SignedIdentifier().id("mypolicy").accessPolicy(accessPolicy); + shareAsyncClient.setAccessPolicy(Collections.singletonList(permission)) + .subscribe(response -> System.out.printf("Setting access policies completed with status code %d", + response.statusCode())); + // END: com.azure.storage.file.shareAsyncClient.setAccessPolicy + } + + /** + * Generates a code sample for using {@link ShareClient#getStatistics()} + */ + public void getStatistics() { + ShareClient shareClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.shareClient.getStatistics + Response response = shareClient.getStatistics(); + System.out.printf("The share is using %d GB", response.value().getShareUsageInGB()); + // END: com.azure.storage.file.shareClient.getStatistics + } + + /** + * Generates a code sample for using {@link ShareAsyncClient#getStatistics()} + */ + public void getStatisticsAsync() { + ShareAsyncClient shareAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.shareAsyncClient.getStatistics + shareAsyncClient.getStatistics() + .subscribe(response -> System.out.printf("The share is using %d GB", + response.value().getShareUsageInGB())); + // END: com.azure.storage.file.shareAsyncClient.getStatistics + } + + /** + * Generates a code sample for using {@link ShareClient#getSnapshotId()} + */ + public void getSnapshotId() { + // BEGIN: com.azure.storage.file.shareClient.getSnapshotId + OffsetDateTime currentTime = OffsetDateTime.of(LocalDateTime.now(), ZoneOffset.UTC); + ShareClient shareClient = new ShareClientBuilder().endpoint("https://${accountName}.file.core.windows.net") + .credential(SASTokenCredential.fromQuery("${SASToken}")) + .shareName("myshare") + .snapshot(currentTime.toString()) + .buildClient(); + shareClient.getSnapshotId(); + // END: com.azure.storage.file.shareClient.getSnapshotId + } + + /** + * Generates a code sample for using {@link ShareAsyncClient#getSnapshotId()} + */ + public void getSnapshotIdAsync() { + // BEGIN: com.azure.storage.file.shareAsyncClient.getSnapshotId + OffsetDateTime currentTime = OffsetDateTime.of(LocalDateTime.now(), ZoneOffset.UTC); + ShareAsyncClient shareAysncClient = new ShareClientBuilder().endpoint("https://${accountName}.file.core.windows.net") + .credential(SASTokenCredential.fromQuery("${SASToken}")) + .shareName("myshare") + .snapshot(currentTime.toString()) + .buildAsyncClient(); + shareAysncClient.getSnapshotId(); + // END: com.azure.storage.file.shareAsyncClient.getSnapshotId + } +} diff --git a/storage/client/file/src/test/java/com/azure/storage/file/DirectoryAsyncClientTests.java b/storage/client/file/src/test/java/com/azure/storage/file/DirectoryAsyncClientTests.java new file mode 100644 index 0000000000000..7fc208fd3f222 --- /dev/null +++ b/storage/client/file/src/test/java/com/azure/storage/file/DirectoryAsyncClientTests.java @@ -0,0 +1,321 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.storage.file; + +import com.azure.core.http.HttpClient; +import com.azure.core.http.policy.HttpLogDetailLevel; +import com.azure.core.implementation.http.UrlBuilder; +import com.azure.core.test.TestMode; +import com.azure.core.util.configuration.ConfigurationManager; +import com.azure.core.util.logging.ClientLogger; +import com.azure.storage.file.models.FileProperty; +import com.azure.storage.file.models.FileRef; +import com.azure.storage.file.models.HandleItem; +import java.time.Duration; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import reactor.test.StepVerifier; + +import static com.azure.storage.file.FileTestHelpers.setupClient; + +public class DirectoryAsyncClientTests extends DirectoryClientTestBase { + private final ClientLogger directoryAsyncLogger = new ClientLogger(DirectoryAsyncClientTests.class); + private static ShareClient shareClient; + private static String shareName = "dirsharename"; + private DirectoryAsyncClient client; + + @Override + public void beforeTest() { + beforeDirectoryTest(); + if (interceptorManager.isPlaybackMode()) { + client = setupClient((connectionString, endpoint) -> new DirectoryClientBuilder() + .connectionString(connectionString) + .endpoint(endpoint) + .shareName(shareName) + .directoryPath(dirName) + .httpClient(interceptorManager.getPlaybackClient()) + .httpLogDetailLevel(HttpLogDetailLevel.BODY_AND_HEADERS) + .buildAsyncClient(), true, directoryAsyncLogger); + } else { + client = setupClient((connectionString, endpoint) -> new DirectoryClientBuilder() + .connectionString(connectionString) + .endpoint(endpoint) + .shareName(shareName) + .directoryPath(dirName) + .httpClient(HttpClient.createDefault().wiretap(true)) + .httpLogDetailLevel(HttpLogDetailLevel.BODY_AND_HEADERS) + .addPolicy(interceptorManager.getRecordPolicy()) + .buildAsyncClient(), false, directoryAsyncLogger); + } + } + + @BeforeClass + public static void beforeClass() { + if (FileTestHelpers.getTestMode() == TestMode.PLAYBACK) { + return; + } + FileServiceClient fileServiceClient = new FileServiceClientBuilder() + .connectionString(ConfigurationManager.getConfiguration().get("AZURE_STORAGE_CONNECTION_STRING")) + .buildClient(); + shareClient = fileServiceClient.getShareClient(shareName); + shareClient.create(); + } + + @AfterClass + public static void tearDown() { + if (FileTestHelpers.getTestMode() == TestMode.PLAYBACK) { + return; + } + shareClient.delete(); + FileTestHelpers.sleepInRecordMode(Duration.ofSeconds(45)); + } + + @Override + public void urlFromDirClient() { + if (interceptorManager.isPlaybackMode()) { + azureStorageFileEndpoint = "https://teststorage.file.core.windows.net/"; + } + UrlBuilder urlBuilder = UrlBuilder.parse(azureStorageFileEndpoint); + String endpointURL = new UrlBuilder().scheme(urlBuilder.scheme()).host(urlBuilder.host()).toString(); + Assert.assertTrue(endpointURL.equals(client.getDirectoryUrl().toString())); + } + + @Override + public void createMinFromDirClient() { + StepVerifier.create(client.create()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + } + + @Override + public void createTwiceFromDirClient() { + client.create().block(); + StepVerifier.create(client.create()) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 409)); + } + + @Override + public void createWithMetadataFromDirClient() { + StepVerifier.create(client.create(basicMetadata)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + } + + @Override + public void getFileClientFromDirClient() { + FileAsyncClient fileClient = client.getFileClient(testResourceNamer.randomName("getFileAsync", 16)); + Assert.assertNotNull(fileClient); + } + + @Override + public void getSubDirectoryClient() { + Assert.assertNotNull(client.getSubDirectoryClient("getSubdirectoryASync")); + } + + @Override + public void deleteFromDirClient() { + StepVerifier.create(client.create()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + StepVerifier.create(client.delete()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 202)) + .verifyComplete(); + } + + @Override + public void deleteNotExistFromDirClient() { + StepVerifier.create(client.delete()) + .verifyErrorSatisfies(exception -> FileTestHelpers.assertExceptionErrorMessage(exception, "ResourceNotFound")); + + } + + @Override + public void getPropertiesFromDirClient() { + StepVerifier.create(client.create()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + StepVerifier.create(client.getProperties()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 200)) + .verifyComplete(); + } + + @Override + public void clearMetadataFromDirClient() { + StepVerifier.create(client.create()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + StepVerifier.create(client.setMetadata(null)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 200)) + .verifyComplete(); + } + + @Override + public void setMetadataFromDirClient() { + client.create().block(); + StepVerifier.create(client.setMetadata(basicMetadata)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 200)) + .verifyComplete(); + } + + @Override + public void setMetadataInvalidKeyFromDirClient() { + client.create().block(); + StepVerifier.create(client.setMetadata(invalidMetadata)) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 400)); + } + + @Override + public void listFilesAndDirectoriesFromDirClient() { + StepVerifier.create(client.create()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + List fileRefs = new ArrayList<>(); + int repeatTimes = 3; + // generate some subdirectories + String fileNameSameLayer = testResourceNamer.randomName("sameLayer", 16); + String fileNameNextLayer = testResourceNamer.randomName("nextLayer", 16); + + for (int i = 0; i < repeatTimes; i++) { + String directoryName = dirName + i; + DirectoryAsyncClient subDirectoryClient = client.getSubDirectoryClient(directoryName); + StepVerifier.create(subDirectoryClient.create()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + fileRefs.add(new FileRef(directoryName, true, null)); + + fileNameSameLayer = fileNameSameLayer + i; + fileNameNextLayer = fileNameNextLayer + i; + + StepVerifier.create(client.createFile(fileNameSameLayer, 1024)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + fileRefs.add(new FileRef(fileNameSameLayer, false, new FileProperty().contentLength(1024))); + StepVerifier.create(subDirectoryClient.createFile(fileNameNextLayer, 1024)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + } + + Collections.sort(fileRefs, new LexicographicComparator()); + StepVerifier.create(client.listFilesAndDirectories(null, null)) + .assertNext(fileRef -> FileTestHelpers.assertFileRefsAreEqual(fileRefs.get(0), fileRef)) + .assertNext(fileRef -> FileTestHelpers.assertFileRefsAreEqual(fileRefs.get(1), fileRef)) + .assertNext(fileRef -> FileTestHelpers.assertFileRefsAreEqual(fileRefs.get(2), fileRef)) + .assertNext(fileRef -> FileTestHelpers.assertFileRefsAreEqual(fileRefs.get(3), fileRef)) + .assertNext(fileRef -> FileTestHelpers.assertFileRefsAreEqual(fileRefs.get(4), fileRef)) + .assertNext(fileRef -> FileTestHelpers.assertFileRefsAreEqual(fileRefs.get(5), fileRef)) + .verifyComplete(); + } + + class LexicographicComparator implements Comparator { + @Override + public int compare(FileRef a, FileRef b) { + return a.name().compareToIgnoreCase(b.name()); + } + } + + @Override + public void getHandlesFromDirClient() { + // TODO: Need to figure out way of creating handlers first. + +// StepVerifier.create(client.create()) +// .assertNext(response -> StorageTestBase.assertResponseStatusCode(response, 201)) +// .verifyComplete(); +// StepVerifier.create(client.getHandles(null, true)) +// .assertNext(response -> Assert.assertNotNull(response)) +// .verifyComplete(); + } + + @Override + public void forceCloseHandlesFromDirClient() { + client.create().block(); + client.createFile("test", 1024); + Iterable handleItems = client.getHandles(null, true).toIterable(); + handleItems.forEach(handleItem -> { + StepVerifier.create(client.forceCloseHandles(handleItem.handleId(), true)) + .assertNext(numOfClosedHandles -> Assert.assertTrue(numOfClosedHandles.longValue() > 0)) + .verifyComplete(); + }); + } + + @Override + public void createSubDirectory() { + StepVerifier.create(client.create()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + StepVerifier.create(client.createSubDirectory(testResourceNamer.randomName("dir", 16))) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + } + + @Override + public void createSubDirectoryWithMetadata() { + StepVerifier.create(client.create()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + StepVerifier.create(client.createSubDirectory(testResourceNamer.randomName("dir", 16), basicMetadata)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + } + + @Override + public void createSubDirectoryTwiceSameMetadata() { + StepVerifier.create(client.create()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + String dirName = testResourceNamer.randomName("dir", 16); + StepVerifier.create(client.createSubDirectory(dirName, basicMetadata)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + StepVerifier.create(client.createSubDirectory(dirName, basicMetadata)) + .verifyErrorSatisfies(exception -> FileTestHelpers.assertExceptionErrorMessage(exception, "ResourceAlreadyExists")); + } + + @Override + public void deleteSubDirectory() { + client.create().block(); + String dirName = testResourceNamer.randomName("dir", 16); + StepVerifier.create(client.createSubDirectory(dirName)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + StepVerifier.create(client.deleteSubDirectory(dirName)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 202)) + .verifyComplete(); + } + + @Override + public void createFileFromDirClient() { + client.create().block(); + StepVerifier.create(client.createFile("testfile", 1024)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + } + + @Override + public void createFileWithoutCreateDirFromDirClient() { + StepVerifier.create(client.createFile("testfile", 1024)) + .verifyErrorSatisfies(response -> FileTestHelpers.assertExceptionStatusCode(response, 404)); + } + + @Override + public void deleteFileFromDirClient() { + client.create().block(); + client.createFile("testfile", 1024).block(); + StepVerifier.create(client.deleteFile("testfile")) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 202)) + .verifyComplete(); + } + + @Override + public void deleteFileWithoutCreateFileFromDirClient() { + client.create().block(); + StepVerifier.create(client.deleteFile("testfile")) + .verifyErrorSatisfies(response -> FileTestHelpers.assertExceptionStatusCode(response, 404)); + } + +} diff --git a/storage/client/file/src/test/java/com/azure/storage/file/DirectoryClientTestBase.java b/storage/client/file/src/test/java/com/azure/storage/file/DirectoryClientTestBase.java new file mode 100644 index 0000000000000..f86f1c2ec14a0 --- /dev/null +++ b/storage/client/file/src/test/java/com/azure/storage/file/DirectoryClientTestBase.java @@ -0,0 +1,113 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.storage.file; + +import com.azure.core.test.TestBase; +import com.azure.core.util.configuration.ConfigurationManager; +import java.util.Collections; +import java.util.Map; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.rules.TestName; + +public abstract class DirectoryClientTestBase extends TestBase { + protected String dirName; + protected String shareName; + + String azureStorageFileEndpoint = ConfigurationManager.getConfiguration().get("AZURE_STORAGE_FILE_ENDPOINT"); + final Map basicMetadata = Collections.singletonMap("test", "metadata"); + final Map invalidMetadata = Collections.singletonMap("1", "metadata"); + + @Rule + public TestName testName = new TestName(); + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + void beforeDirectoryTest() { + dirName = testResourceNamer.randomName("directory", 16); + } + + /** + * Gets the name of the current test being run. + *

                  + * NOTE: This could not be implemented in the base class using {@link TestName} because it always returns {@code + * null}. See https://stackoverflow.com/a/16113631/4220757. + * + * @return The name of the current test. + */ + @Override + protected String testName() { + return testName.getMethodName(); + } + + @Test + public abstract void urlFromDirClient(); + + @Test + public abstract void getFileClientFromDirClient(); + + @Test + public abstract void getSubDirectoryClient(); + + @Test + public abstract void createMinFromDirClient(); + + @Test + public abstract void createTwiceFromDirClient(); + + @Test + public abstract void createWithMetadataFromDirClient(); + + @Test + public abstract void deleteFromDirClient(); + + @Test + public abstract void deleteNotExistFromDirClient(); + + @Test + public abstract void getPropertiesFromDirClient(); + + @Test + public abstract void clearMetadataFromDirClient(); + + @Test + public abstract void setMetadataFromDirClient(); + + @Test + public abstract void setMetadataInvalidKeyFromDirClient(); + + @Test + public abstract void listFilesAndDirectoriesFromDirClient(); + + @Test + public abstract void getHandlesFromDirClient(); + + @Test + public abstract void forceCloseHandlesFromDirClient(); + + @Test + public abstract void createSubDirectory(); + + @Test + public abstract void createSubDirectoryWithMetadata(); + + @Test + public abstract void createSubDirectoryTwiceSameMetadata(); + + @Test + public abstract void deleteSubDirectory(); + + @Test + public abstract void createFileFromDirClient(); + + @Test + public abstract void createFileWithoutCreateDirFromDirClient(); + + @Test + public abstract void deleteFileFromDirClient(); + + @Test + public abstract void deleteFileWithoutCreateFileFromDirClient(); +} diff --git a/storage/client/file/src/test/java/com/azure/storage/file/DirectoryClientTests.java b/storage/client/file/src/test/java/com/azure/storage/file/DirectoryClientTests.java new file mode 100644 index 0000000000000..64103f0d110d4 --- /dev/null +++ b/storage/client/file/src/test/java/com/azure/storage/file/DirectoryClientTests.java @@ -0,0 +1,259 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.storage.file; + +import com.azure.core.http.HttpClient; +import com.azure.core.http.policy.HttpLogDetailLevel; +import com.azure.core.implementation.http.UrlBuilder; +import com.azure.core.test.TestMode; +import com.azure.core.util.configuration.ConfigurationManager; +import com.azure.core.util.logging.ClientLogger; +import com.azure.storage.file.models.FileRef; +import com.azure.storage.file.models.StorageErrorException; +import java.time.Duration; +import java.util.Iterator; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; + +import static com.azure.storage.file.FileTestHelpers.setupClient; +import static org.junit.Assert.assertTrue; + +public class DirectoryClientTests extends DirectoryClientTestBase { + private final ClientLogger directoryLogger = new ClientLogger(DirectoryClientTests.class); + private static String shareName = "dirsharename"; + private static ShareClient shareClient; + private DirectoryClient directoryClient; + + @Override + public void beforeTest() { + beforeDirectoryTest(); + if (interceptorManager.isPlaybackMode()) { + directoryClient = setupClient((connectionString, endpoint) -> new DirectoryClientBuilder() + .connectionString(connectionString) + .endpoint(endpoint) + .shareName(shareName) + .directoryPath(dirName) + .httpClient(interceptorManager.getPlaybackClient()) + .httpLogDetailLevel(HttpLogDetailLevel.BODY_AND_HEADERS) + .buildClient(), true, directoryLogger); + } else { + directoryClient = setupClient((connectionString, endpoint) -> new DirectoryClientBuilder() + .connectionString(connectionString) + .endpoint(endpoint) + .shareName(shareName) + .directoryPath(dirName) + .httpClient(HttpClient.createDefault().wiretap(true)) + .httpLogDetailLevel(HttpLogDetailLevel.BODY_AND_HEADERS) + .addPolicy(interceptorManager.getRecordPolicy()) + .buildClient(), false, directoryLogger); + } + } + + @BeforeClass + public static void beforeClass() { + if (FileTestHelpers.getTestMode() == TestMode.PLAYBACK) { + return; + } + FileServiceClient fileServiceClient = new FileServiceClientBuilder() + .connectionString(ConfigurationManager.getConfiguration().get("AZURE_STORAGE_CONNECTION_STRING")) + .buildClient(); + shareClient = fileServiceClient.getShareClient(shareName); + shareClient.create(); + } + + @AfterClass + public static void tearDown() { + if (FileTestHelpers.getTestMode() == TestMode.PLAYBACK) { + return; + } + shareClient.delete(); + FileTestHelpers.sleepInRecordMode(Duration.ofSeconds(45)); + } + + @Override + public void urlFromDirClient() { + if (interceptorManager.isPlaybackMode()) { + azureStorageFileEndpoint = "https://teststorage.file.core.windows.net/"; + } + UrlBuilder urlBuilder = UrlBuilder.parse(azureStorageFileEndpoint); + String endpointURL = new UrlBuilder().scheme(urlBuilder.scheme()).host(urlBuilder.host()).toString(); + Assert.assertEquals(endpointURL, directoryClient.getDirectoryUrl().toString()); + } + + @Override + public void createMinFromDirClient() { + FileTestHelpers.assertResponseStatusCode(directoryClient.create(), 201); + } + + @Override + public void createTwiceFromDirClient() { + directoryClient.create(); + thrown.expect(StorageErrorException.class); + thrown.expectMessage("ResourceAlreadyExists"); + directoryClient.create(); + } + + @Override + public void createWithMetadataFromDirClient() { + FileTestHelpers.assertResponseStatusCode(directoryClient.create(basicMetadata), 201); + } + + @Override + public void getFileClientFromDirClient() { + Assert.assertNotNull(directoryClient.getFileClient(testResourceNamer.randomName("getFileSync", 16))); + } + + @Override + public void getSubDirectoryClient() { + Assert.assertNotNull(directoryClient.getSubDirectoryClient("getSubdirectorySync")); + } + + @Override + public void deleteFromDirClient() { + directoryClient.create(); + FileTestHelpers.assertResponseStatusCode(directoryClient.delete(), 202); + } + + @Override + public void deleteNotExistFromDirClient() { + thrown.expect(StorageErrorException.class); + thrown.expectMessage("ResourceNotFound"); + directoryClient.delete(); + } + + @Override + public void getPropertiesFromDirClient() { + directoryClient.create(); + FileTestHelpers.assertResponseStatusCode(directoryClient.getProperties(), 200); + } + + @Override + public void clearMetadataFromDirClient() { + directoryClient.create(); + FileTestHelpers.assertResponseStatusCode(directoryClient.setMetadata(null), 200); + } + + @Override + public void setMetadataFromDirClient() { + directoryClient.create(); + FileTestHelpers.assertResponseStatusCode(directoryClient.setMetadata(basicMetadata), 200); + } + + @Override + public void setMetadataInvalidKeyFromDirClient() { + directoryClient.create(); + thrown.expect(StorageErrorException.class); + thrown.expectMessage("InvalidMetadata"); + directoryClient.setMetadata(invalidMetadata); + } + + @Override + public void listFilesAndDirectoriesFromDirClient() { + FileTestHelpers.assertResponseStatusCode(directoryClient.create(), 201); + int repeatTimes = 3; + String fileNameSameLayer = testResourceNamer.randomName("sameLayer", 16); + String fileNameNextLayer = testResourceNamer.randomName("nextLayer", 16); + for (int i = 0; i < repeatTimes; i++) { + DirectoryClient subDirClient = directoryClient.getSubDirectoryClient(dirName + i); + FileTestHelpers.assertResponseStatusCode(subDirClient.create(), 201); + fileNameSameLayer = fileNameSameLayer + i; + fileNameNextLayer = fileNameNextLayer + i; + FileTestHelpers.assertResponseStatusCode(directoryClient.createFile(fileNameSameLayer, 1024), 201); + FileTestHelpers.assertResponseStatusCode(subDirClient.createFile(fileNameNextLayer, 1024), 201); + } + + Iterable fileRefs = directoryClient.listFilesAndDirectories(); + + int count = 0; + Iterator it = fileRefs.iterator(); + while (it.hasNext()) { + count++; + FileRef ref = it.next(); + Assert.assertNotNull(ref); + if (!ref.isDirectory()) { + assertTrue("It is supposed to list the files in same layer.", ref.name().contains("samelayer")); + } + } + Assert.assertEquals(repeatTimes * 2, count); + } + + @Override + public void getHandlesFromDirClient() { + // TODO: Need to open channel and create handlers first. +// StorageTestBase.assertResponseStatusCode(directoryClient.create(), 201); +// Assert.assertTrue(directoryClient.getHandles(null, true).iterator().hasNext()); + } + + @Override + public void forceCloseHandlesFromDirClient() { + FileTestHelpers.assertResponseStatusCode(directoryClient.create(), 201); + directoryClient.getHandles(null, true).forEach( + handleItem -> { + directoryClient.forceCloseHandles(handleItem.handleId(), true).forEach( + numberOfClosedHandles -> assertTrue(numberOfClosedHandles > 0) + ); + } + ); + } + + @Override + public void createSubDirectory() { + FileTestHelpers.assertResponseStatusCode(directoryClient.create(), 201); + FileTestHelpers.assertResponseStatusCode(directoryClient.createSubDirectory(testResourceNamer.randomName("directory", 16)), 201); + } + + @Override + public void createSubDirectoryWithMetadata() { + FileTestHelpers.assertResponseStatusCode(directoryClient.create(), 201); + FileTestHelpers.assertResponseStatusCode(directoryClient.createSubDirectory(testResourceNamer.randomName("directory", 16), basicMetadata), 201); + } + + @Override + public void createSubDirectoryTwiceSameMetadata() { + directoryClient.create(); + String dirName = testResourceNamer.randomName("dir", 16); + FileTestHelpers.assertResponseStatusCode(directoryClient.createSubDirectory(dirName, basicMetadata), 201); + thrown.expect(StorageErrorException.class); + thrown.expectMessage("ResourceAlreadyExists"); + directoryClient.createSubDirectory(dirName, basicMetadata); + } + + + @Override + public void deleteSubDirectory() { + directoryClient.create(); + String dirName = testResourceNamer.randomName("dir", 16); + FileTestHelpers.assertResponseStatusCode(directoryClient.createSubDirectory(dirName), 201); + FileTestHelpers.assertResponseStatusCode(directoryClient.deleteSubDirectory(dirName), 202); + } + + @Override + public void createFileFromDirClient() { + directoryClient.create(); + FileTestHelpers.assertResponseStatusCode(directoryClient.createFile("testfile", 1024), 201); + } + + @Override + public void createFileWithoutCreateDirFromDirClient() { + thrown.expect(StorageErrorException.class); + thrown.expectMessage("ParentNotFound"); + directoryClient.createFile("testfile", 1024); + } + + @Override + public void deleteFileFromDirClient() { + directoryClient.create(); + directoryClient.createFile("testfile", 1024); + FileTestHelpers.assertResponseStatusCode(directoryClient.deleteFile("testfile"), 202); + } + + @Override + public void deleteFileWithoutCreateFileFromDirClient() { + directoryClient.create(); + thrown.expect(StorageErrorException.class); + thrown.expectMessage("ResourceNotFound"); + directoryClient.deleteFile("testfile"); + } + +} diff --git a/storage/client/file/src/test/java/com/azure/storage/file/FileAsyncClientTest.java b/storage/client/file/src/test/java/com/azure/storage/file/FileAsyncClientTest.java new file mode 100644 index 0000000000000..3f8199113888c --- /dev/null +++ b/storage/client/file/src/test/java/com/azure/storage/file/FileAsyncClientTest.java @@ -0,0 +1,215 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.storage.file; + +import com.azure.core.http.HttpClient; +import com.azure.core.http.policy.HttpLogDetailLevel; +import com.azure.core.test.TestMode; +import com.azure.core.util.configuration.ConfigurationManager; +import com.azure.core.util.logging.ClientLogger; +import com.azure.storage.file.models.FileHTTPHeaders; +import com.azure.storage.file.models.HandleItem; +import java.io.File; +import java.net.URL; +import java.nio.file.Files; +import java.time.Duration; +import java.util.Arrays; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import reactor.core.publisher.Flux; +import reactor.test.StepVerifier; + +import static com.azure.storage.file.FileTestHelpers.assertTwoFilesAreSame; +import static com.azure.storage.file.FileTestHelpers.setupClient; + +public class FileAsyncClientTest extends FileClientTestBase { + private final ClientLogger fileAsyncLogger = new ClientLogger(FileAsyncClientTest.class); + String filePath; + private static String shareName = "filesharename"; + private static String dirName = "testdir/"; + private static ShareClient shareClient; + private FileAsyncClient fileAsyncClient; + + @Override + public void beforeTest() { + filePath = dirName + testResourceNamer.randomName("file", 16); + if (interceptorManager.isPlaybackMode()) { + fileAsyncClient = setupClient((connectionString, endpoint) -> new FileClientBuilder() + .connectionString(connectionString) + .shareName(shareName) + .filePath(filePath) + .endpoint(endpoint) + .httpClient(interceptorManager.getPlaybackClient()) + .httpLogDetailLevel(HttpLogDetailLevel.BODY_AND_HEADERS) + .buildAsyncClient(), true, fileAsyncLogger); + } else { + fileAsyncClient = setupClient((connectionString, endpoint) -> new FileClientBuilder() + .connectionString(connectionString) + .shareName(shareName) + .filePath(filePath) + .endpoint(endpoint) + .httpClient(HttpClient.createDefault().wiretap(true)) + .httpLogDetailLevel(HttpLogDetailLevel.BODY_AND_HEADERS) + .addPolicy(interceptorManager.getRecordPolicy()) + .buildAsyncClient(), false, fileAsyncLogger); + } + } + @BeforeClass + public static void beforeClass() { + if (FileTestHelpers.getTestMode() == TestMode.PLAYBACK) { + return; + } + FileServiceClient fileServiceClient = new FileServiceClientBuilder() + .connectionString(ConfigurationManager.getConfiguration().get("AZURE_STORAGE_CONNECTION_STRING")) + .buildClient(); + shareClient = fileServiceClient.getShareClient(shareName); + shareClient.create(); + shareClient.createDirectory(dirName); + } + + @AfterClass + public static void tearDown() { + if (FileTestHelpers.getTestMode() == TestMode.PLAYBACK) { + return; + } + shareClient.delete(); + FileTestHelpers.sleepInRecordMode(Duration.ofSeconds(45)); + } + + @Override + public void createFromFileClient() { + StepVerifier.create(fileAsyncClient.create(1024)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + StepVerifier.create(fileAsyncClient.getProperties()) + .assertNext(filePropertiesResponse -> Assert.assertTrue(filePropertiesResponse.value().contentLength() == 1024)) + .verifyComplete(); + } + + @Override + public void createExcessMaxSizeFromFileClient() { + StepVerifier.create(fileAsyncClient.create(1024 * 1024 * 1024 * 1024, null, null)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + StepVerifier.create(fileAsyncClient.getProperties()) + .assertNext(filePropertiesResponse -> Assert.assertTrue(filePropertiesResponse.value().contentLength() == 0)) + .verifyComplete(); + } + + @Override + public void startCopy() throws Exception { + fileAsyncClient.create(1024).block(); + String sourceURL = fileAsyncClient.getFileUrl().toString() + "/" + shareName + "/" + filePath; + StepVerifier.create(fileAsyncClient.startCopy(sourceURL, null)) + .assertNext(response -> { + FileTestHelpers.assertResponseStatusCode(response, 202); + Assert.assertTrue(response.value().copyId() != null); + }) + .verifyComplete(); + } + + @Override + public void abortCopy() { + // TODO: need to mock a pending copy process. + } + + @Override + public void downloadWithProperties() { + fileAsyncClient.create(1024, null, null).block(); + StepVerifier.create(fileAsyncClient.downloadWithProperties()) + .assertNext(response -> FileTestHelpers.assertResponseListStatusCode(response, Arrays.asList(200, 206))) + .verifyComplete(); + } + + @Override + public void uploadToStorageAndDownloadToFile() throws Exception { + URL fileFolder = FileClientTestBase.class.getClassLoader().getResource("testfiles"); + File uploadFile = new File(fileFolder.getPath() + "/helloworld"); + File downloadFile = new File(fileFolder.getPath() + "/testDownload"); + + if (!Files.exists(downloadFile.toPath())) { + downloadFile.createNewFile(); + } + fileAsyncClient.create(uploadFile.length()).block(); + StepVerifier.create(fileAsyncClient.uploadFromFile(uploadFile.toString())) + .verifyComplete(); + StepVerifier.create(fileAsyncClient.downloadToFile(downloadFile.toString())) + .verifyComplete(); + + assertTwoFilesAreSame(uploadFile, downloadFile); + } + + @Override + public void deleteFromFileClient() { + fileAsyncClient.create(1024, null, null).block(); + StepVerifier.create(fileAsyncClient.delete()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 202)) + .verifyComplete(); + } + + @Override + public void getPropertiesFromFileClient() { + fileAsyncClient.create(1024).block(); + StepVerifier.create(fileAsyncClient.getProperties()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 200)) + .verifyComplete(); + } + + @Override + public void setHttpHeadersFromFileClient() { + fileAsyncClient.create(1024).block(); + FileHTTPHeaders headers = new FileHTTPHeaders(); + headers.fileContentMD5(new byte[0]); + StepVerifier.create(fileAsyncClient.setHttpHeaders(1024, headers)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 200)) + .verifyComplete(); + } + + @Override + public void setMeatadataFromFileClient() { + fileAsyncClient.create(1024).block(); + StepVerifier.create(fileAsyncClient.setMetadata(basicMetadata)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 200)) + .verifyComplete(); + } + + @Override + public void upload() { + fileAsyncClient.create(1024 * 5, null, null).block(); + StepVerifier.create(fileAsyncClient.upload(Flux.just(defaultData), defaultData.readableBytes())) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + } + + @Override + public void listRangesFromFileClient() { + fileAsyncClient.create(512, null, null).block(); + fileAsyncClient.upload(Flux.just(defaultData), defaultData.readableBytes()).block(); + StepVerifier.create(fileAsyncClient.listRanges()) + .assertNext(response -> Assert.assertTrue(response.start() == 0 && response.end() == 511)) + .verifyComplete(); + } + + @Override + public void listHandlesFromFileClient() { + //TODO: need to create a handle first + fileAsyncClient.create(1024).block(); + StepVerifier.create(fileAsyncClient.listHandles()) + .verifyComplete(); + } + + @Override + public void forceCloseHandlesFromFileClient() { + //TODO: need to figureout create a handle first + fileAsyncClient.create(1024).block(); + Iterable handles = fileAsyncClient.listHandles(10).toIterable(); + handles.forEach( + response -> { + StepVerifier.create(fileAsyncClient.forceCloseHandles(response.handleId())) + .assertNext(forceCloseHandles -> Assert.assertTrue(forceCloseHandles > 0)) + .verifyComplete(); + } + ); + } +} diff --git a/storage/client/file/src/test/java/com/azure/storage/file/FileClientTest.java b/storage/client/file/src/test/java/com/azure/storage/file/FileClientTest.java new file mode 100644 index 0000000000000..2ba243ff90464 --- /dev/null +++ b/storage/client/file/src/test/java/com/azure/storage/file/FileClientTest.java @@ -0,0 +1,202 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.storage.file; + +import com.azure.core.http.HttpClient; +import com.azure.core.http.policy.HttpLogDetailLevel; +import com.azure.core.http.rest.Response; +import com.azure.core.test.TestMode; +import com.azure.core.util.configuration.ConfigurationManager; +import com.azure.core.util.logging.ClientLogger; +import com.azure.storage.file.models.FileCopyInfo; +import com.azure.storage.file.models.FileHTTPHeaders; +import com.azure.storage.file.models.FileInfo; +import com.azure.storage.file.models.FileProperties; +import com.azure.storage.file.models.FileRange; +import java.io.File; +import java.net.URL; +import java.nio.file.Files; +import java.time.Duration; +import java.util.Arrays; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; + +import static com.azure.storage.file.FileTestHelpers.assertTwoFilesAreSame; +import static com.azure.storage.file.FileTestHelpers.setupClient; + +public class FileClientTest extends FileClientTestBase { + private final ClientLogger fileLogger = new ClientLogger(FileClientTest.class); + private static String shareName = "filesharename"; + private static String dirName = "testdir/"; + private static ShareClient shareClient; + String filePath; + + private FileClient fileClient; + + @Override + public void beforeTest() { + filePath = dirName + testResourceNamer.randomName("file", 16); + if (interceptorManager.isPlaybackMode()) { + fileClient = setupClient((connectionString, endpoint) -> new FileClientBuilder() + .connectionString(connectionString) + .shareName(shareName) + .filePath(filePath) + .endpoint(endpoint) + .httpClient(interceptorManager.getPlaybackClient()) + .httpLogDetailLevel(HttpLogDetailLevel.BODY_AND_HEADERS) + .buildClient(), true, fileLogger); + } else { + fileClient = setupClient((connectionString, endpoint) -> new FileClientBuilder() + .connectionString(connectionString) + .shareName(shareName) + .filePath(filePath) + .endpoint(endpoint) + .httpClient(HttpClient.createDefault().wiretap(true)) + .httpLogDetailLevel(HttpLogDetailLevel.BODY_AND_HEADERS) + .addPolicy(interceptorManager.getRecordPolicy()) + .buildClient(), false, fileLogger); + } + } + @BeforeClass + public static void beforeClass() { + if (FileTestHelpers.getTestMode() == TestMode.PLAYBACK) { + return; + } + FileServiceClient fileServiceClient = new FileServiceClientBuilder() + .connectionString(ConfigurationManager.getConfiguration().get("AZURE_STORAGE_CONNECTION_STRING")) + .buildClient(); + shareClient = fileServiceClient.getShareClient(shareName); + shareClient.create(); + shareClient.createDirectory(dirName); + } + + @AfterClass + public static void tearDown() { + if (FileTestHelpers.getTestMode() == TestMode.PLAYBACK) { + return; + } + shareClient.delete(); + FileTestHelpers.sleepInRecordMode(Duration.ofSeconds(45)); + } + + @Override + public void createFromFileClient() { + FileTestHelpers.assertResponseStatusCode(fileClient.create(1024), 201); + Assert.assertTrue(fileClient.getProperties().value().contentLength() == 1024); + } + + @Override + public void createExcessMaxSizeFromFileClient() { + FileTestHelpers.assertResponseStatusCode(fileClient.create(1024 * 1024 * 1024 * 1024, null, null), 201); + Assert.assertTrue(fileClient.getProperties().value().contentLength() == 0); + } + + @Override + public void startCopy() throws Exception { + FileTestHelpers.assertResponseStatusCode(fileClient.create(1024, null, null), 201); + String sourceURL = fileClient.getFileUrl().toString() + "/" + shareName + "/" + filePath; + Response copyInfoResponse = fileClient.startCopy(sourceURL, null); + FileTestHelpers.assertResponseStatusCode(copyInfoResponse, 202); + Assert.assertTrue(copyInfoResponse.value().copyId() != null); + } + + @Override + public void abortCopy() { + // TODO: Need to construct or mock a copy with pending status + } + + @Override + public void downloadWithProperties() { + fileClient.create(1024, null, null); + FileRange range = new FileRange(0, 1024L); + FileTestHelpers.assertResponseListStatusCode(fileClient.downloadWithProperties(range, null), Arrays.asList(200, 206)); + } + + @Override + public void uploadToStorageAndDownloadToFile() throws Exception { + URL fileFolder = FileClientTestBase.class.getClassLoader().getResource("testfiles"); + File uploadFile = new File(fileFolder.getPath() + "/helloworld"); + File downloadFile = new File(fileFolder.getPath() + "/testDownload"); + + if (!Files.exists(downloadFile.toPath())) { + downloadFile.createNewFile(); + } + + fileClient.create(uploadFile.length()); + fileClient.uploadFromFile(uploadFile.toString()); + fileClient.downloadToFile(downloadFile.toString()); + assertTwoFilesAreSame(uploadFile, downloadFile); + } + + @Override + public void deleteFromFileClient() { + fileClient.create(1024, null, null); + FileTestHelpers.assertResponseStatusCode(fileClient.delete(), 202); + } + + @Override + public void getPropertiesFromFileClient() { + fileClient.create(1024, null, null); + Response propertiesResponse = fileClient.getProperties(); + Assert.assertNotNull(propertiesResponse.value()); + Assert.assertNotNull(propertiesResponse.value().contentLength() == 1024); + Assert.assertNotNull(propertiesResponse.value().eTag()); + Assert.assertNotNull(propertiesResponse.value().lastModified()); + } + + @Override + public void setHttpHeadersFromFileClient() { + fileClient.create(1024, null, null); + FileHTTPHeaders headers = new FileHTTPHeaders(); + headers.fileContentMD5(new byte[0]); + Response response = fileClient.setHttpHeaders(1024, headers); + FileTestHelpers.assertResponseStatusCode(response, 200); + Assert.assertNotNull(response.value().eTag()); + } + + @Override + public void setMeatadataFromFileClient() { + fileClient.create(1024, null, null); + FileTestHelpers.assertResponseStatusCode(fileClient.setMetadata(basicMetadata), 200); + } + + @Override + public void upload() { + fileClient.create(1024 * 5, null, null); + FileTestHelpers.assertResponseStatusCode(fileClient.upload(defaultData, defaultData.readableBytes()), 201); + } + + @Override + public void listRangesFromFileClient() { + fileClient.create(1024, null, null); + fileClient.upload(defaultData, defaultData.readableBytes()); + fileClient.listRanges(new FileRange(0, 511L)).forEach( + fileRangeInfo -> { + Assert.assertTrue(fileRangeInfo.start() == 0); + Assert.assertTrue(fileRangeInfo.end() == 511); + } + ); + } + + @Override + public void listHandlesFromFileClient() { + //TODO: need to find a way to create handles. + fileClient.create(1024); + fileClient.listHandles().forEach( + handleItem -> { + Assert.assertNotNull(handleItem.handleId()); + } + ); + } + + @Override + public void forceCloseHandlesFromFileClient() { + fileClient.create(1024, null, null); + fileClient.listHandles(10).forEach( + handleItem -> { + Assert.assertNotNull(fileClient.forceCloseHandles(handleItem.handleId())); + } + ); + } +} diff --git a/storage/client/file/src/test/java/com/azure/storage/file/FileClientTestBase.java b/storage/client/file/src/test/java/com/azure/storage/file/FileClientTestBase.java new file mode 100644 index 0000000000000..9aba9e055bbc3 --- /dev/null +++ b/storage/client/file/src/test/java/com/azure/storage/file/FileClientTestBase.java @@ -0,0 +1,81 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.storage.file; + +import com.azure.core.test.TestBase; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.Map; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.rules.TestName; + +public abstract class FileClientTestBase extends TestBase { + final Map basicMetadata = Collections.singletonMap("test", "metadata"); + static final String DEFAULT_TEXT = "default"; + final ByteBuf defaultData = Unpooled.wrappedBuffer(DEFAULT_TEXT.getBytes(StandardCharsets.UTF_8)); + + @Rule + public TestName testName = new TestName(); + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + /** + * Gets the name of the current test being run. + *

                  + * NOTE: This could not be implemented in the base class using {@link TestName} because it always returns {@code + * null}. See https://stackoverflow.com/a/16113631/4220757. + * + * @return The name of the current test. + */ + @Override + protected String testName() { + return testName.getMethodName(); + } + + @Test + public abstract void createFromFileClient(); + + @Test + public abstract void createExcessMaxSizeFromFileClient(); + + @Test + public abstract void startCopy() throws Exception; + + @Test + public abstract void abortCopy(); + + @Test + public abstract void downloadWithProperties(); + + @Test + public abstract void uploadToStorageAndDownloadToFile() throws Exception; + + @Test + public abstract void deleteFromFileClient(); + + @Test + public abstract void getPropertiesFromFileClient(); + + @Test + public abstract void setHttpHeadersFromFileClient(); + + @Test + public abstract void setMeatadataFromFileClient(); + + @Test + public abstract void upload(); + + @Test + public abstract void listRangesFromFileClient() throws Exception; + + @Test + public abstract void listHandlesFromFileClient(); + + @Test + public abstract void forceCloseHandlesFromFileClient(); +} diff --git a/storage/client/file/src/test/java/com/azure/storage/file/FileServiceClientAsyncTests.java b/storage/client/file/src/test/java/com/azure/storage/file/FileServiceClientAsyncTests.java new file mode 100644 index 0000000000000..cc302acca59a5 --- /dev/null +++ b/storage/client/file/src/test/java/com/azure/storage/file/FileServiceClientAsyncTests.java @@ -0,0 +1,472 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.storage.file; + +import com.azure.core.http.HttpClient; +import com.azure.core.http.policy.HttpLogDetailLevel; +import com.azure.core.util.logging.ClientLogger; +import com.azure.storage.file.models.CorsRule; +import com.azure.storage.file.models.FileServiceProperties; +import com.azure.storage.file.models.ListSharesOptions; +import com.azure.storage.file.models.Metrics; +import com.azure.storage.file.models.RetentionPolicy; +import com.azure.storage.file.models.ShareItem; +import com.azure.storage.file.models.ShareProperties; +import com.azure.storage.file.models.StorageErrorException; +import java.time.Duration; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import reactor.test.StepVerifier; + +import static com.azure.storage.file.FileTestHelpers.setupClient; +import static org.junit.Assert.fail; + +public class FileServiceClientAsyncTests extends FileServiceClientTestBase { + private final ClientLogger fileServiceAsyncLogger = new ClientLogger(FileServiceClientAsyncTests.class); + + private FileServiceAsyncClient fileServiceAsyncClient; + + @Override + public void beforeTest() { + shareName = getShareName(); + + if (interceptorManager.isPlaybackMode()) { + fileServiceAsyncClient = setupClient((connectionString, endpoint) -> new FileServiceClientBuilder() + .connectionString(connectionString) + .endpoint(endpoint) + .httpClient(interceptorManager.getPlaybackClient()) + .httpLogDetailLevel(HttpLogDetailLevel.BODY_AND_HEADERS) + .buildAsyncClient(), true, fileServiceAsyncLogger); + } else { + fileServiceAsyncClient = setupClient((connectionString, endpoint) -> new FileServiceClientBuilder() + .connectionString(connectionString) + .endpoint(endpoint) + .httpClient(HttpClient.createDefault().wiretap(true)) + .httpLogDetailLevel(HttpLogDetailLevel.BODY_AND_HEADERS) + .addPolicy(interceptorManager.getRecordPolicy()) + .buildAsyncClient(), false, fileServiceAsyncLogger); + } + } + + @Override + public void afterTest() { + fileServiceAsyncClient.listShares(new ListSharesOptions().prefix(shareName)) + .collectList() + .block() + .forEach(share -> { + ShareAsyncClient client = fileServiceAsyncClient.getShareAsyncClient(share.name()); + try { + client.delete().block(); + } catch (StorageErrorException ex) { + // Share already deleted, that's what we wanted anyways. + } + }); + } + + @Override + public void getShareDoesNotCreateAShare() { + ShareAsyncClient client = fileServiceAsyncClient.getShareAsyncClient(shareName); + try { + client.getStatistics().block(); + fail("getShareAsyncClient shouldn't create a share in Azure."); + } catch (Exception ex) { + FileTestHelpers.assertExceptionStatusCode(ex, 404); + } + } + + @Override + public void createShare() { + StepVerifier.create(fileServiceAsyncClient.createShare(shareName)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + } + + @Override + public void createShareTwiceSameMetadata() { + StepVerifier.create(fileServiceAsyncClient.createShare(shareName)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(fileServiceAsyncClient.createShare(shareName)) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 409)); + } + + @Override + public void createShareTwiceDifferentMetadata() { + Map metadata = Collections.singletonMap("test", "metadata"); + + StepVerifier.create(fileServiceAsyncClient.createShare(shareName)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(fileServiceAsyncClient.createShare(shareName, metadata, null)) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 409)); + } + + @Override + public void createShareInvalidQuota() { + StepVerifier.create(fileServiceAsyncClient.createShare(shareName, null, -1)) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 400)); + + StepVerifier.create(fileServiceAsyncClient.createShare(shareName, null, 9999999)) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 400)); + } + + @Override + public void deleteShare() { + StepVerifier.create(fileServiceAsyncClient.createShare(shareName)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(fileServiceAsyncClient.deleteShare(shareName)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 202)) + .verifyComplete(); + } + + @Override + public void deleteShareDoesNotExist() { + StepVerifier.create(fileServiceAsyncClient.deleteShare(shareName)) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 404)); + } + + @Override + public void deleteThenCreateShareFromFileServiceClient() { + StepVerifier.create(fileServiceAsyncClient.createShare(shareName)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(fileServiceAsyncClient.deleteShare(shareName)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 202)) + .verifyComplete(); + + FileTestHelpers.sleepInRecordMode(Duration.ofSeconds(45)); + + StepVerifier.create(fileServiceAsyncClient.createShare(shareName)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + } + + @Override + public void deleteThenCreateShareTooSoonFromFileServiceClient() { + StepVerifier.create(fileServiceAsyncClient.createShare(shareName)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(fileServiceAsyncClient.deleteShare(shareName)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 202)) + .verifyComplete(); + + StepVerifier.create(fileServiceAsyncClient.createShare(shareName)) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 409)); + } + + @Override + public void listShares() { + LinkedList testShares = new LinkedList<>(); + for (int i = 0; i < 3; i++) { + ShareItem share = new ShareItem().name(shareName + i) + .properties(new ShareProperties().quota(2)); + + testShares.add(share); + StepVerifier.create(fileServiceAsyncClient.createShare(share.name(), share.metadata(), share.properties().quota())) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + } + + StepVerifier.create(fileServiceAsyncClient.listShares(defaultOptions())) + .assertNext(share -> FileTestHelpers.assertSharesAreEqual(testShares.pop(), share)) + .assertNext(share -> FileTestHelpers.assertSharesAreEqual(testShares.pop(), share)) + .assertNext(share -> FileTestHelpers.assertSharesAreEqual(testShares.pop(), share)) + .verifyComplete(); + } + + @Override + public void listSharesWithPrefix() { + LinkedList testShares = new LinkedList<>(); + for (int i = 0; i < 3; i++) { + ShareItem share = new ShareItem().properties(new ShareProperties().quota(2)); + + if (i % 2 == 0) { + share.name(shareName + "prefix" + i); + testShares.add(share); + } else { + share.name(shareName + i); + } + + StepVerifier.create(fileServiceAsyncClient.createShare(share.name(), share.metadata(), share.properties().quota())) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + } + + StepVerifier.create(fileServiceAsyncClient.listShares(defaultOptions().prefix(shareName + "prefix"))) + .assertNext(share -> FileTestHelpers.assertSharesAreEqual(testShares.pop(), share)) + .assertNext(share -> FileTestHelpers.assertSharesAreEqual(testShares.pop(), share)) + .verifyComplete(); + } + + @Override + public void listSharesWithLimit() { + LinkedList testShares = new LinkedList<>(); + for (int i = 0; i < 3; i++) { + ShareItem share = new ShareItem().name(shareName + i) + .properties(new ShareProperties().quota(2)); + + testShares.add(share); + StepVerifier.create(fileServiceAsyncClient.createShare(share.name(), share.metadata(), share.properties().quota())) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + } + + StepVerifier.create(fileServiceAsyncClient.listShares(defaultOptions().maxResults(2))) + .assertNext(share -> FileTestHelpers.assertSharesAreEqual(testShares.pop(), share)) + .assertNext(share -> FileTestHelpers.assertSharesAreEqual(testShares.pop(), share)) + .verifyComplete(); + } + + @Override + public void listSharesInvalidMaxResults() { + StepVerifier.create(fileServiceAsyncClient.listShares(defaultOptions().maxResults(-1))) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 400)); + + StepVerifier.create(fileServiceAsyncClient.listShares(defaultOptions().maxResults(0))) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 400)); + } + + @Override + public void listSharesIncludeMetadata() { + Map metadata = Collections.singletonMap("test", "metadata"); + + LinkedList testShares = new LinkedList<>(); + for (int i = 0; i < 3; i++) { + ShareItem share = new ShareItem().name(shareName + i) + .properties(new ShareProperties().quota(2)); + + if (i % 2 == 0) { + share.metadata(metadata); + } + + testShares.add(share); + StepVerifier.create(fileServiceAsyncClient.createShare(share.name(), share.metadata(), share.properties().quota())) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + } + + StepVerifier.create(fileServiceAsyncClient.listShares(defaultOptions().includeMetadata(true))) + .assertNext(share -> FileTestHelpers.assertSharesAreEqual(testShares.pop(), share)) + .assertNext(share -> FileTestHelpers.assertSharesAreEqual(testShares.pop(), share)) + .assertNext(share -> FileTestHelpers.assertSharesAreEqual(testShares.pop(), share)) + .verifyComplete(); + } + + @Override + public void listSharesIncludeSnapshots() { + LinkedList testShares = new LinkedList<>(); + for (int i = 0; i < 3; i++) { + ShareItem share = new ShareItem().name(shareName + i) + .properties(new ShareProperties().quota(2)); + + ShareAsyncClient client = fileServiceAsyncClient.getShareAsyncClient(share.name()); + + StepVerifier.create(client.create(null, share.properties().quota())) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + if (i % 2 == 0) { + StepVerifier.create(client.createSnapshot()) + .assertNext(response -> { + testShares.add(new ShareItem().name(share.name()) + .snapshot(response.value().snapshot()) + .properties(share.properties())); + + FileTestHelpers.assertResponseStatusCode(response, 201); + }) + .verifyComplete(); + } + + testShares.add(share); + } + + StepVerifier.create(fileServiceAsyncClient.listShares(defaultOptions().includeSnapshots(true))) + .assertNext(share -> FileTestHelpers.assertSharesAreEqual(testShares.pop(), share)) + .assertNext(share -> FileTestHelpers.assertSharesAreEqual(testShares.pop(), share)) + .assertNext(share -> FileTestHelpers.assertSharesAreEqual(testShares.pop(), share)) + .assertNext(share -> FileTestHelpers.assertSharesAreEqual(testShares.pop(), share)) + .assertNext(share -> FileTestHelpers.assertSharesAreEqual(testShares.pop(), share)) + .verifyComplete(); + } + + @Override + public void listSharesIncludeMetadataAndSnapshots() { + Map metadata = Collections.singletonMap("test", "metadata"); + + LinkedList testShares = new LinkedList<>(); + for (int i = 0; i < 3; i++) { + ShareItem share = new ShareItem().name(shareName + i) + .properties(new ShareProperties().quota(2)); + + if (i % 2 == 0) { + share.metadata(metadata); + } + + ShareAsyncClient client = fileServiceAsyncClient.getShareAsyncClient(share.name()); + + StepVerifier.create(client.create(share.metadata(), share.properties().quota())) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + if (i % 2 == 0) { + StepVerifier.create(client.createSnapshot()) + .assertNext(response -> { + testShares.add(new ShareItem().name(share.name()) + .snapshot(response.value().snapshot()) + .properties(share.properties())); + + FileTestHelpers.assertResponseStatusCode(response, 201); + }) + .verifyComplete(); + } + + testShares.add(share); + } + + StepVerifier.create(fileServiceAsyncClient.listShares(defaultOptions().includeMetadata(true).includeSnapshots(true))) + .assertNext(share -> FileTestHelpers.assertSharesAreEqual(testShares.pop(), share)) + .assertNext(share -> FileTestHelpers.assertSharesAreEqual(testShares.pop(), share)) + .assertNext(share -> FileTestHelpers.assertSharesAreEqual(testShares.pop(), share)) + .assertNext(share -> FileTestHelpers.assertSharesAreEqual(testShares.pop(), share)) + .assertNext(share -> FileTestHelpers.assertSharesAreEqual(testShares.pop(), share)) + .verifyComplete(); + } + + @Override + public void setFileServiceProperties() { + FileServiceProperties originalProperties = fileServiceAsyncClient.getProperties().block().value(); + + RetentionPolicy retentionPolicy = new RetentionPolicy().enabled(true) + .days(3); + + Metrics metrics = new Metrics().enabled(true) + .includeAPIs(false) + .retentionPolicy(retentionPolicy) + .version("1.0"); + + FileServiceProperties updatedProperties = new FileServiceProperties().hourMetrics(metrics) + .minuteMetrics(metrics) + .cors(new ArrayList<>()); + + StepVerifier.create(fileServiceAsyncClient.setProperties(updatedProperties)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 202)) + .verifyComplete(); + + StepVerifier.create(fileServiceAsyncClient.getProperties()) + .assertNext(response -> FileTestHelpers.assertFileServicePropertiesAreEqual(updatedProperties, response.value())) + .verifyComplete(); + + StepVerifier.create(fileServiceAsyncClient.setProperties(originalProperties)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 202)) + .verifyComplete(); + + StepVerifier.create(fileServiceAsyncClient.getProperties()) + .assertNext(response -> FileTestHelpers.assertFileServicePropertiesAreEqual(originalProperties, response.value())) + .verifyComplete(); + } + + @Override + public void setPropertiesTooManyRules() { + RetentionPolicy retentionPolicy = new RetentionPolicy().enabled(true) + .days(3); + + Metrics metrics = new Metrics().enabled(true) + .includeAPIs(false) + .retentionPolicy(retentionPolicy) + .version("1.0"); + + List cors = new ArrayList<>(); + for (int i = 0; i < 6; i++) { + cors.add(new CorsRule()); + } + + FileServiceProperties properties = new FileServiceProperties().hourMetrics(metrics) + .minuteMetrics(metrics) + .cors(cors); + + StepVerifier.create(fileServiceAsyncClient.setProperties(properties)) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 400)); + } + + @Override + public void setPropertiesInvalidAllowedHeader() { + RetentionPolicy retentionPolicy = new RetentionPolicy().enabled(true) + .days(3); + + Metrics metrics = new Metrics().enabled(true) + .includeAPIs(false) + .retentionPolicy(retentionPolicy) + .version("1.0"); + + FileServiceProperties properties = new FileServiceProperties().hourMetrics(metrics) + .minuteMetrics(metrics) + .cors(Collections.singletonList(new CorsRule().allowedHeaders(reallyLongString))); + + StepVerifier.create(fileServiceAsyncClient.setProperties(properties)) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 400)); + } + + @Override + public void setPropertiesInvalidExposedHeader() { + RetentionPolicy retentionPolicy = new RetentionPolicy().enabled(true) + .days(3); + + Metrics metrics = new Metrics().enabled(true) + .includeAPIs(false) + .retentionPolicy(retentionPolicy) + .version("1.0"); + + FileServiceProperties properties = new FileServiceProperties().hourMetrics(metrics) + .minuteMetrics(metrics) + .cors(Collections.singletonList(new CorsRule().exposedHeaders(reallyLongString))); + + StepVerifier.create(fileServiceAsyncClient.setProperties(properties)) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 400)); + } + + @Override + public void setPropertiesInvalidAllowedOrigin() { + RetentionPolicy retentionPolicy = new RetentionPolicy().enabled(true) + .days(3); + + Metrics metrics = new Metrics().enabled(true) + .includeAPIs(false) + .retentionPolicy(retentionPolicy) + .version("1.0"); + + FileServiceProperties properties = new FileServiceProperties().hourMetrics(metrics) + .minuteMetrics(metrics) + .cors(Collections.singletonList(new CorsRule().allowedOrigins(reallyLongString))); + + StepVerifier.create(fileServiceAsyncClient.setProperties(properties)) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 400)); + } + + @Override + public void setPropertiesInvalidAllowedMethod() { + RetentionPolicy retentionPolicy = new RetentionPolicy().enabled(true) + .days(3); + + Metrics metrics = new Metrics().enabled(true) + .includeAPIs(false) + .retentionPolicy(retentionPolicy) + .version("1.0"); + + FileServiceProperties properties = new FileServiceProperties().hourMetrics(metrics) + .minuteMetrics(metrics) + .cors(Collections.singletonList(new CorsRule().allowedMethods("NOTAREALHTTPMETHOD"))); + + StepVerifier.create(fileServiceAsyncClient.setProperties(properties)) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 400)); + } +} diff --git a/storage/client/file/src/test/java/com/azure/storage/file/FileServiceClientTestBase.java b/storage/client/file/src/test/java/com/azure/storage/file/FileServiceClientTestBase.java new file mode 100644 index 0000000000000..6a34f910052f3 --- /dev/null +++ b/storage/client/file/src/test/java/com/azure/storage/file/FileServiceClientTestBase.java @@ -0,0 +1,121 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.storage.file; + +import com.azure.core.test.TestBase; +import com.azure.storage.file.models.ListSharesOptions; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; + +public abstract class FileServiceClientTestBase extends TestBase { + String shareName; + + String reallyLongString = "thisisareallylongstringthatexceedsthe64characterlimitallowedoncertainproperties"; + + @Rule + public TestName testName = new TestName(); + + /** + * Gets the name of the current test being run. + *

                  + * NOTE: This could not be implemented in the base class using {@link TestName} because it always returns {@code + * null}. See https://stackoverflow.com/a/16113631/4220757. + * + * @return The name of the current test. + */ + @Override + protected String testName() { + return testName.getMethodName(); + } + + String getShareName() { + return testResourceNamer.randomName("share", 16).toLowerCase(); + } + + ListSharesOptions defaultOptions() { + return new ListSharesOptions().prefix(shareName); + } + + @Test + public abstract void getShareDoesNotCreateAShare(); + + @Test + public abstract void createShare(); + + @Test + public abstract void createShareTwiceSameMetadata(); + + @Test + public abstract void createShareTwiceDifferentMetadata(); + + @Test + public abstract void createShareInvalidQuota(); + + @Test + public abstract void deleteShare(); + + @Test + public abstract void deleteShareDoesNotExist(); + + @Test + public abstract void deleteThenCreateShareFromFileServiceClient(); + + /** + * Cannot re-create a share within 30 seconds of it being deleted. + */ + @Test + public abstract void deleteThenCreateShareTooSoonFromFileServiceClient(); + + @Test + public abstract void listShares(); + + @Test + public abstract void listSharesWithPrefix(); + + @Test + public abstract void listSharesWithLimit(); + + @Test + public abstract void listSharesInvalidMaxResults(); + + @Test + public abstract void listSharesIncludeMetadata(); + + @Test + public abstract void listSharesIncludeSnapshots(); + + @Test + public abstract void listSharesIncludeMetadataAndSnapshots(); + + @Test + public abstract void setFileServiceProperties(); + + @Test + public abstract void setPropertiesTooManyRules(); + + /** + * A header in AllowedHeaders is not allowed to exceed 256 characters. + */ + @Test + public abstract void setPropertiesInvalidAllowedHeader(); + + /** + * A header in ExposedHeaders is not allowed to exceed 256 characters. + */ + @Test + public abstract void setPropertiesInvalidExposedHeader(); + + /** + * An origin in AllowedOrigins is not allowed to exceed 256 characters. + */ + @Test + public abstract void setPropertiesInvalidAllowedOrigin(); + + /** + * AllowedMethods only supports DELETE, GET, HEAD, MERGE, POST, OPTIONS, and PUT. + */ + @Test + public abstract void setPropertiesInvalidAllowedMethod(); +} diff --git a/storage/client/file/src/test/java/com/azure/storage/file/FileServiceClientTests.java b/storage/client/file/src/test/java/com/azure/storage/file/FileServiceClientTests.java new file mode 100644 index 0000000000000..3377458e2584c --- /dev/null +++ b/storage/client/file/src/test/java/com/azure/storage/file/FileServiceClientTests.java @@ -0,0 +1,479 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.storage.file; + +import com.azure.core.http.HttpClient; +import com.azure.core.http.policy.HttpLogDetailLevel; +import com.azure.core.http.rest.Response; +import com.azure.core.util.logging.ClientLogger; +import com.azure.storage.file.models.CorsRule; +import com.azure.storage.file.models.FileServiceProperties; +import com.azure.storage.file.models.ListSharesOptions; +import com.azure.storage.file.models.Metrics; +import com.azure.storage.file.models.RetentionPolicy; +import com.azure.storage.file.models.ShareInfo; +import com.azure.storage.file.models.ShareItem; +import com.azure.storage.file.models.ShareProperties; +import com.azure.storage.file.models.ShareSnapshotInfo; +import com.azure.storage.file.models.StorageErrorException; +import java.time.Duration; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import static com.azure.storage.file.FileTestHelpers.setupClient; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.fail; + +public class FileServiceClientTests extends FileServiceClientTestBase { + private final ClientLogger fileServiceLogger = new ClientLogger(FileServiceClientTests.class); + + private FileServiceClient fileServiceClient; + + @Override + public void beforeTest() { + shareName = getShareName(); + + if (interceptorManager.isPlaybackMode()) { + fileServiceClient = setupClient((connectionString, endpoint) -> new FileServiceClientBuilder() + .connectionString(connectionString) + .endpoint(endpoint) + .httpClient(interceptorManager.getPlaybackClient()) + .httpLogDetailLevel(HttpLogDetailLevel.BODY_AND_HEADERS) + .buildClient(), true, fileServiceLogger); + } else { + fileServiceClient = setupClient((connectionString, endpoint) -> new FileServiceClientBuilder() + .connectionString(connectionString) + .endpoint(endpoint) + .httpClient(HttpClient.createDefault().wiretap(true)) + .httpLogDetailLevel(HttpLogDetailLevel.BODY_AND_HEADERS) + .addPolicy(interceptorManager.getRecordPolicy()) + .buildClient(), false, fileServiceLogger); + } + } + + @Override + public void afterTest() { + for (ShareItem share : fileServiceClient.listShares(new ListSharesOptions().prefix(shareName))) { + ShareClient client = fileServiceClient.getShareClient(share.name()); + try { + client.delete(); + } catch (StorageErrorException ex) { + // Share already deleted, that's what we wanted anyways. + } + } + } + + @Override + public void getShareDoesNotCreateAShare() { + ShareClient client = fileServiceClient.getShareClient(shareName); + try { + client.getStatistics(); + fail("getShareAsyncClient shouldn't create a share in Azure."); + } catch (Exception ex) { + FileTestHelpers.assertExceptionStatusCode(ex, 404); + } + } + + @Override + public void createShare() { + FileTestHelpers.assertResponseStatusCode(fileServiceClient.createShare(shareName), 201); + } + + @Override + public void createShareTwiceSameMetadata() { + FileTestHelpers.assertResponseStatusCode(fileServiceClient.createShare(shareName), 201); + + try { + fileServiceClient.createShare(shareName); + } catch (Exception exception) { + FileTestHelpers.assertExceptionStatusCode(exception, 409); + } + } + + @Override + public void createShareTwiceDifferentMetadata() { + Map metadata = Collections.singletonMap("test", "metadata"); + + FileTestHelpers.assertResponseStatusCode(fileServiceClient.createShare(shareName), 201); + + try { + fileServiceClient.createShare(shareName, metadata, null); + fail("Attempting to create the share twice with different metadata should throw an exception."); + } catch (Exception exception) { + FileTestHelpers.assertExceptionStatusCode(exception, 409); + } + } + + @Override + public void createShareInvalidQuota() { + try { + fileServiceClient.createShare(shareName, null, -1); + fail("Attempting to create a share with a negative quota should throw an exception."); + } catch (Exception exception) { + FileTestHelpers.assertExceptionStatusCode(exception, 400); + } + + try { + fileServiceClient.createShare(shareName, null, 9999999); + fail("Attempting to create a share with a quota above 5120 GB should throw an exception."); + } catch (Exception exception) { + FileTestHelpers.assertExceptionStatusCode(exception, 400); + } + } + + @Override + public void deleteShare() { + FileTestHelpers.assertResponseStatusCode(fileServiceClient.createShare(shareName), 201); + FileTestHelpers.assertResponseStatusCode(fileServiceClient.deleteShare(shareName), 202); + } + + @Override + public void deleteShareDoesNotExist() { + try { + fileServiceClient.deleteShare(shareName); + fail("Attempting to delete a share that doesn't exist should throw an exception."); + } catch (Exception exception) { + FileTestHelpers.assertExceptionStatusCode(exception, 404); + } + } + + @Override + public void deleteThenCreateShareFromFileServiceClient() { + FileTestHelpers.assertResponseStatusCode(fileServiceClient.createShare(shareName), 201); + FileTestHelpers.assertResponseStatusCode(fileServiceClient.deleteShare(shareName), 202); + + FileTestHelpers.sleepInRecordMode(Duration.ofSeconds(45)); + + FileTestHelpers.assertResponseStatusCode(fileServiceClient.createShare(shareName), 201); + } + + @Override + public void deleteThenCreateShareTooSoonFromFileServiceClient() { + FileTestHelpers.assertResponseStatusCode(fileServiceClient.createShare(shareName), 201); + FileTestHelpers.assertResponseStatusCode(fileServiceClient.deleteShare(shareName), 202); + + try { + fileServiceClient.createShare(shareName); + fail("Attempting to re-create a share within 30 seconds of deleting it should throw an exception."); + } catch (Exception exception) { + FileTestHelpers.assertExceptionStatusCode(exception, 409); + } + } + + @Override + public void listShares() { + LinkedList testShares = new LinkedList<>(); + for (int i = 0; i < 3; i++) { + ShareItem share = new ShareItem().name(shareName + i) + .properties(new ShareProperties().quota(2)); + + testShares.add(share); + FileTestHelpers.assertResponseStatusCode(fileServiceClient.createShare(share.name(), share.metadata(), share.properties().quota()), 201); + } + + Iterator shares = fileServiceClient.listShares(defaultOptions()).iterator(); + for (int i = 0; i < 3; i++) { + FileTestHelpers.assertSharesAreEqual(testShares.pop(), shares.next()); + } + assertFalse(shares.hasNext()); + } + + @Override + public void listSharesWithPrefix() { + LinkedList testShares = new LinkedList<>(); + for (int i = 0; i < 3; i++) { + ShareItem share = new ShareItem().properties(new ShareProperties().quota(2)); + + if (i % 2 == 0) { + share.name(shareName + "prefix" + i); + testShares.add(share); + } else { + share.name(shareName + i); + } + + FileTestHelpers.assertResponseStatusCode(fileServiceClient.createShare(share.name(), share.metadata(), share.properties().quota()), 201); + } + + Iterator shares = fileServiceClient.listShares(defaultOptions().prefix(shareName + "prefix")).iterator(); + for (int i = 0; i < 2; i++) { + FileTestHelpers.assertSharesAreEqual(testShares.pop(), shares.next()); + } + assertFalse(shares.hasNext()); + } + + @Override + public void listSharesWithLimit() { + LinkedList testShares = new LinkedList<>(); + for (int i = 0; i < 3; i++) { + ShareItem share = new ShareItem().name(shareName + i) + .properties(new ShareProperties().quota(2)); + + testShares.add(share); + FileTestHelpers.assertResponseStatusCode(fileServiceClient.createShare(share.name(), share.metadata(), share.properties().quota()), 201); + } + + Iterator shares = fileServiceClient.listShares(defaultOptions().maxResults(2)).iterator(); + for (int i = 0; i < 2; i++) { + FileTestHelpers.assertSharesAreEqual(testShares.pop(), shares.next()); + } + assertFalse(shares.hasNext()); + } + + @Override + public void listSharesInvalidMaxResults() { + try { + fileServiceClient.listShares(defaultOptions().maxResults(-1)).iterator().hasNext(); + fail("Attempting to list shares with a negative maximum should throw an error"); + } catch (Exception exception) { + FileTestHelpers.assertExceptionStatusCode(exception, 400); + } + + try { + fileServiceClient.listShares(defaultOptions().maxResults(0)).iterator().hasNext(); + fail("Attempting to list shares with a zero maximum should throw an error"); + } catch (Exception exception) { + FileTestHelpers.assertExceptionStatusCode(exception, 400); + } + } + + @Override + public void listSharesIncludeMetadata() { + Map metadata = Collections.singletonMap("test", "metadata"); + + LinkedList testShares = new LinkedList<>(); + for (int i = 0; i < 3; i++) { + ShareItem share = new ShareItem().name(shareName + i) + .properties(new ShareProperties().quota(2)); + + if (i % 2 == 0) { + share.metadata(metadata); + } + + testShares.add(share); + FileTestHelpers.assertResponseStatusCode(fileServiceClient.createShare(share.name(), share.metadata(), share.properties().quota()), 201); + } + + Iterator shares = fileServiceClient.listShares(defaultOptions().includeMetadata(true)).iterator(); + for (int i = 0; i < 3; i++) { + FileTestHelpers.assertSharesAreEqual(testShares.pop(), shares.next()); + } + assertFalse(shares.hasNext()); + } + + @Override + public void listSharesIncludeSnapshots() { + LinkedList testShares = new LinkedList<>(); + for (int i = 0; i < 3; i++) { + ShareItem share = new ShareItem().name(shareName + i) + .properties(new ShareProperties().quota(2)); + + ShareClient client = fileServiceClient.getShareClient(share.name()); + + Response createResponse = client.create(null, share.properties().quota()); + FileTestHelpers.assertResponseStatusCode(createResponse, 201); + + if (i % 2 == 0) { + Response snapshotResponse = client.createSnapshot(); + FileTestHelpers.assertResponseStatusCode(snapshotResponse, 201); + + testShares.add(new ShareItem().name(share.name()) + .snapshot(snapshotResponse.value().snapshot()) + .properties(new ShareProperties().quota(share.properties().quota()))); + } + + testShares.add(share); + } + + Iterator shares = fileServiceClient.listShares(defaultOptions().includeSnapshots(true)).iterator(); + for (int i = 0; i < 5; i++) { + FileTestHelpers.assertSharesAreEqual(testShares.pop(), shares.next()); + } + assertFalse(shares.hasNext()); + } + + @Override + public void listSharesIncludeMetadataAndSnapshots() { + Map metadata = Collections.singletonMap("test", "metadata"); + + LinkedList testShares = new LinkedList<>(); + for (int i = 0; i < 3; i++) { + ShareItem share = new ShareItem().name(shareName + i) + .properties(new ShareProperties().quota(2)); + + if (i % 2 == 0) { + share.metadata(metadata); + } + + ShareClient client = fileServiceClient.getShareClient(share.name()); + + Response createResponse = client.create(share.metadata(), share.properties().quota()); + FileTestHelpers.assertResponseStatusCode(createResponse, 201); + + if (i % 2 == 0) { + Response snapshotResponse = client.createSnapshot(); + FileTestHelpers.assertResponseStatusCode(snapshotResponse, 201); + + testShares.add(new ShareItem().name(share.name()) + .snapshot(snapshotResponse.value().snapshot()) + .properties(share.properties())); + } + + testShares.add(share); + } + + Iterator shares = fileServiceClient.listShares(defaultOptions().includeMetadata(true).includeSnapshots(true)).iterator(); + for (int i = 0; i < 5; i++) { + FileTestHelpers.assertSharesAreEqual(testShares.pop(), shares.next()); + } + assertFalse(shares.hasNext()); + } + + @Override + public void setFileServiceProperties() { + FileServiceProperties originalProperties = fileServiceClient.getProperties().value(); + + RetentionPolicy retentionPolicy = new RetentionPolicy().enabled(true) + .days(3); + + Metrics metrics = new Metrics().enabled(true) + .includeAPIs(false) + .retentionPolicy(retentionPolicy) + .version("1.0"); + + FileServiceProperties updatedProperties = new FileServiceProperties().hourMetrics(metrics) + .minuteMetrics(metrics) + .cors(new ArrayList<>()); + + FileTestHelpers.assertResponseStatusCode(fileServiceClient.setProperties(updatedProperties), 202); + + Response getResponse = fileServiceClient.getProperties(); + FileTestHelpers.assertResponseStatusCode(getResponse, 200); + FileTestHelpers.assertFileServicePropertiesAreEqual(updatedProperties, getResponse.value()); + + FileTestHelpers.assertResponseStatusCode(fileServiceClient.setProperties(originalProperties), 202); + + getResponse = fileServiceClient.getProperties(); + FileTestHelpers.assertResponseStatusCode(getResponse, 200); + FileTestHelpers.assertFileServicePropertiesAreEqual(originalProperties, getResponse.value()); + } + + @Override + public void setPropertiesTooManyRules() { + RetentionPolicy retentionPolicy = new RetentionPolicy().enabled(true) + .days(3); + + Metrics metrics = new Metrics().enabled(true) + .includeAPIs(false) + .retentionPolicy(retentionPolicy) + .version("1.0"); + + List cors = new ArrayList<>(); + for (int i = 0; i < 6; i++) { + cors.add(new CorsRule()); + } + + FileServiceProperties properties = new FileServiceProperties().hourMetrics(metrics) + .minuteMetrics(metrics) + .cors(cors); + + try { + fileServiceClient.setProperties(properties); + fail("Attempting to set more than 5 CorsRules on files should throw an exception."); + } catch (Exception exception) { + FileTestHelpers.assertExceptionStatusCode(exception, 400); + } + } + + @Override + public void setPropertiesInvalidAllowedHeader() { + RetentionPolicy retentionPolicy = new RetentionPolicy().enabled(true) + .days(3); + + Metrics metrics = new Metrics().enabled(true) + .includeAPIs(false) + .retentionPolicy(retentionPolicy) + .version("1.0"); + + FileServiceProperties properties = new FileServiceProperties().hourMetrics(metrics) + .minuteMetrics(metrics) + .cors(Collections.singletonList(new CorsRule().allowedHeaders(reallyLongString))); + + try { + fileServiceClient.setProperties(properties); + fail("Attempting to set an allowed header longer than 64 characters should throw an exception."); + } catch (Exception exception) { + FileTestHelpers.assertExceptionStatusCode(exception, 400); + } + } + + @Override + public void setPropertiesInvalidExposedHeader() { + RetentionPolicy retentionPolicy = new RetentionPolicy().enabled(true) + .days(3); + + Metrics metrics = new Metrics().enabled(true) + .includeAPIs(false) + .retentionPolicy(retentionPolicy) + .version("1.0"); + + FileServiceProperties properties = new FileServiceProperties().hourMetrics(metrics) + .minuteMetrics(metrics) + .cors(Collections.singletonList(new CorsRule().exposedHeaders(reallyLongString))); + + try { + fileServiceClient.setProperties(properties); + fail("Attempting to set an exposed header longer than 64 characters should throw an exception."); + } catch (Exception exception) { + FileTestHelpers.assertExceptionStatusCode(exception, 400); + } + } + + @Override + public void setPropertiesInvalidAllowedOrigin() { + RetentionPolicy retentionPolicy = new RetentionPolicy().enabled(true) + .days(3); + + Metrics metrics = new Metrics().enabled(true) + .includeAPIs(false) + .retentionPolicy(retentionPolicy) + .version("1.0"); + + FileServiceProperties properties = new FileServiceProperties().hourMetrics(metrics) + .minuteMetrics(metrics) + .cors(Collections.singletonList(new CorsRule().allowedOrigins(reallyLongString))); + + try { + fileServiceClient.setProperties(properties); + fail("Attempting to set an allowed origin longer than 64 characters should throw an exception."); + } catch (Exception exception) { + FileTestHelpers.assertExceptionStatusCode(exception, 400); + } + } + + @Override + public void setPropertiesInvalidAllowedMethod() { + RetentionPolicy retentionPolicy = new RetentionPolicy().enabled(true) + .days(3); + + Metrics metrics = new Metrics().enabled(true) + .includeAPIs(false) + .retentionPolicy(retentionPolicy) + .version("1.0"); + + FileServiceProperties properties = new FileServiceProperties().hourMetrics(metrics) + .minuteMetrics(metrics) + .cors(Collections.singletonList(new CorsRule().allowedMethods("NOTAREALHTTPMETHOD"))); + + try { + fileServiceClient.setProperties(properties); + fail("Attempting to set an invalid allowed method should throw an exception."); + } catch (Exception exception) { + FileTestHelpers.assertExceptionStatusCode(exception, 400); + } + } +} diff --git a/storage/client/file/src/test/java/com/azure/storage/file/FileTestHelpers.java b/storage/client/file/src/test/java/com/azure/storage/file/FileTestHelpers.java new file mode 100644 index 0000000000000..44a7d27bf7c50 --- /dev/null +++ b/storage/client/file/src/test/java/com/azure/storage/file/FileTestHelpers.java @@ -0,0 +1,257 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.storage.file; + +import com.azure.core.http.rest.Response; +import com.azure.core.implementation.util.ImplUtils; +import com.azure.core.test.InterceptorManager; +import com.azure.core.test.TestBase; +import com.azure.core.test.TestMode; +import com.azure.core.util.configuration.ConfigurationManager; +import com.azure.core.util.logging.ClientLogger; +import com.azure.storage.file.models.CorsRule; +import com.azure.storage.file.models.FileRef; +import com.azure.storage.file.models.FileServiceProperties; +import com.azure.storage.file.models.Metrics; +import com.azure.storage.file.models.RetentionPolicy; +import com.azure.storage.file.models.ShareItem; +import com.azure.storage.file.models.SignedIdentifier; +import com.azure.storage.file.models.StorageErrorException; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.security.NoSuchAlgorithmException; +import java.time.Duration; +import java.util.List; +import java.util.Locale; +import java.util.function.BiFunction; +import org.junit.Assert; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +class FileTestHelpers { + private static final String AZURE_TEST_MODE = "AZURE_TEST_MODE"; + + static T setupClient(BiFunction clientBuilder, boolean isPlayback, ClientLogger logger) { + String connectionString = "DefaultEndpointsProtocol=https;AccountName=teststorage;AccountKey=atestaccountkey;EndpointSuffix=core.windows.net"; + String endpoint = "https://teststorage.file.core.windows.net/"; + + if (!isPlayback) { + connectionString = ConfigurationManager.getConfiguration().get("AZURE_STORAGE_CONNECTION_STRING"); + endpoint = ConfigurationManager.getConfiguration().get("AZURE_STORAGE_FILE_ENDPOINT"); + } + + if (ImplUtils.isNullOrEmpty(connectionString) && ImplUtils.isNullOrEmpty(endpoint)) { + logger.asWarning().log("Connection string or endpoint must be set to buildClient the testing client"); + fail(); + return null; + } + + return clientBuilder.apply(connectionString, endpoint); + } + + static ShareClientBuilder createShareClientWithSnapshot(InterceptorManager interceptorManager, String shareName, String snapshot) { + String connectionString = "DefaultEndpointsProtocol=https;AccountName=teststorage;AccountKey=atestaccountkey;EndpointSuffix=core.windows.net"; + String endpoint = "https://teststorage.file.core.windows.net/"; + + ShareClientBuilder shareClientBuilder; + if (!interceptorManager.isPlaybackMode()) { + connectionString = ConfigurationManager.getConfiguration().get("AZURE_STORAGE_CONNECTION_STRING"); + endpoint = ConfigurationManager.getConfiguration().get("AZURE_STORAGE_FILE_ENDPOINT"); + shareClientBuilder = new ShareClientBuilder() + .endpoint(endpoint) + .connectionString(connectionString) + .addPolicy(interceptorManager.getRecordPolicy()) + .shareName(shareName) + .snapshot(snapshot); + } else { + shareClientBuilder = new ShareClientBuilder() + .endpoint(endpoint) + .connectionString(connectionString) + .httpClient(interceptorManager.getPlaybackClient()) + .shareName(shareName) + .snapshot(snapshot); + } + return shareClientBuilder; + } + + static void assertResponseStatusCode(Response response, int expectedStatusCode) { + assertEquals(expectedStatusCode, response.statusCode()); + } + + static void assertResponseListStatusCode(Response response, List expectedStatusCodeList) { + for (Integer expectedStatusCode: expectedStatusCodeList) { + if (expectedStatusCode == response.statusCode()) { + return; + } + } + fail("The response status code did not include in the list."); + } + + static void assertExceptionStatusCode(Throwable throwable, int expectedStatusCode) { + assertTrue(throwable instanceof StorageErrorException); + StorageErrorException exception = (StorageErrorException) throwable; + assertEquals(expectedStatusCode, exception.response().statusCode()); + } + + static void assertExceptionErrorMessage(Throwable throwable, String message) { + assertTrue(throwable instanceof StorageErrorException); + StorageErrorException exception = (StorageErrorException) throwable; + assertTrue(exception.getMessage().contains(message)); + } + + static void assertExceptionStatusCode(Runnable thrower, int expectedStatusCode) { + try { + thrower.run(); + fail(); + } catch (Exception ex) { + assertTrue(ex instanceof StorageErrorException); + StorageErrorException exception = (StorageErrorException) ex; + assertEquals(expectedStatusCode, exception.response().statusCode()); + } + } + + static void sleepInRecordMode(Duration duration) { + if (getTestMode() == TestMode.RECORD) { + sleep(duration); + } + } + + static void sleep(Duration duration) { + try { + Thread.sleep(duration.toMillis()); + } catch (InterruptedException ex) { + // Ignore the exception + } + } + + static void assertSharesAreEqual(ShareItem expected, ShareItem actual) { + if (expected == null) { + assertNull(actual); + } else { + assertEquals(expected.name(), actual.name()); + assertEquals(expected.properties().quota(), actual.properties().quota()); + + if (expected.metadata() != null) { + assertEquals(expected.metadata(), actual.metadata()); + } + + if (expected.snapshot() != null) { + assertEquals(expected.snapshot(), actual.snapshot()); + } + } + } + + static void assertFileServicePropertiesAreEqual(FileServiceProperties expected, FileServiceProperties actual) { + if (expected == null) { + assertNull(actual); + } else { + assertMetricsAreEqual(expected.hourMetrics(), actual.hourMetrics()); + assertMetricsAreEqual(expected.minuteMetrics(), actual.minuteMetrics()); + assertCorsAreEqual(expected.cors(), actual.cors()); + } + } + + static void assertFileRefsAreEqual(FileRef expected, FileRef actual) { + if (expected == null) { + assertNull(actual); + } else { + assertEquals(expected.name(), actual.name()); + assertEquals(expected.isDirectory(), actual.isDirectory()); + + if (expected.fileProperties() != null && actual.fileProperties() != null) { + assertEquals(expected.fileProperties().contentLength(), actual.fileProperties().contentLength()); + } + } + } + + static void assertPermissionsAreEqual(SignedIdentifier expected, SignedIdentifier actual) { + assertEquals(expected.id(), actual.id()); + assertEquals(expected.accessPolicy().permission(), actual.accessPolicy().permission()); + assertEquals(expected.accessPolicy().start(), actual.accessPolicy().start()); + assertEquals(expected.accessPolicy().expiry(), actual.accessPolicy().expiry()); + } + + static TestMode getTestMode() { + final Logger logger = LoggerFactory.getLogger(TestBase.class); + final String azureTestMode = ConfigurationManager.getConfiguration().get(AZURE_TEST_MODE); + + if (azureTestMode != null) { + try { + return TestMode.valueOf(azureTestMode.toUpperCase(Locale.US)); + } catch (IllegalArgumentException e) { + if (logger.isErrorEnabled()) { + logger.error("Could not parse '{}' into TestEnum. Using 'Playback' mode.", azureTestMode); + } + + return TestMode.PLAYBACK; + } + } + + if (logger.isInfoEnabled()) { + logger.info("Environment variable '{}' has not been set yet. Using 'Playback' mode.", AZURE_TEST_MODE); + } + return TestMode.PLAYBACK; + } + + private static void assertMetricsAreEqual(Metrics expected, Metrics actual) { + if (expected == null) { + assertNull(actual); + } else { + assertEquals(expected.enabled(), actual.enabled()); + assertEquals(expected.includeAPIs(), actual.includeAPIs()); + assertEquals(expected.version(), actual.version()); + assertRetentionPoliciesAreEqual(expected.retentionPolicy(), actual.retentionPolicy()); + } + } + + static void assertTwoFilesAreSame(File f1, File f2) throws IOException, NoSuchAlgorithmException { + List uploadFileString = Files.readAllLines(f1.toPath()); + List downloadFileString = Files.readAllLines(f2.toPath()); + if (uploadFileString != null && downloadFileString != null) { + downloadFileString.removeAll(uploadFileString); + } + while (!downloadFileString.isEmpty()) { + Assert.assertTrue("The download file is supposed to be the same as the upload file.", downloadFileString.get(0).isEmpty()); + downloadFileString.remove(0); + } + } + + private static void assertRetentionPoliciesAreEqual(RetentionPolicy expected, RetentionPolicy actual) { + if (expected == null) { + assertNull(actual); + } else { + assertEquals(expected.days(), actual.days()); + assertEquals(expected.enabled(), actual.enabled()); + } + } + + private static void assertCorsAreEqual(List expected, List actual) { + if (expected == null) { + assertTrue(ImplUtils.isNullOrEmpty(actual)); + } else { + assertEquals(expected.size(), actual.size()); + for (int i = 0; i < expected.size(); i++) { + assertCorRulesAreEqual(expected.get(i), actual.get(i)); + } + } + } + + private static void assertCorRulesAreEqual(CorsRule expected, CorsRule actual) { + if (expected == null) { + assertNull(actual); + } else { + assertEquals(expected.allowedHeaders(), actual.allowedHeaders()); + assertEquals(expected.allowedMethods(), actual.allowedMethods()); + assertEquals(expected.allowedOrigins(), actual.allowedOrigins()); + assertEquals(expected.exposedHeaders(), actual.exposedHeaders()); + assertEquals(expected.maxAgeInSeconds(), actual.maxAgeInSeconds()); + } + } +} diff --git a/storage/client/file/src/test/java/com/azure/storage/file/LargeFileTest.java b/storage/client/file/src/test/java/com/azure/storage/file/LargeFileTest.java new file mode 100644 index 0000000000000..aecce061802c8 --- /dev/null +++ b/storage/client/file/src/test/java/com/azure/storage/file/LargeFileTest.java @@ -0,0 +1,129 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.storage.file; + +import com.azure.core.test.TestBase; +import com.azure.core.test.TestMode; +import com.azure.core.util.configuration.ConfigurationManager; +import com.azure.core.util.logging.ClientLogger; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.RandomAccessFile; +import java.net.URL; +import java.nio.file.Files; +import java.security.MessageDigest; +import java.time.Duration; +import java.time.OffsetDateTime; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; + +import static org.junit.Assert.fail; +import static org.junit.Assume.assumeTrue; + +public class LargeFileTest extends TestBase { + private final ClientLogger largeFileLogger = new ClientLogger(LargeFileTest.class); + private final String azureStorageConnectionString = ConfigurationManager.getConfiguration().get("AZURE_STORAGE_CONNECTION_STRING"); + private static final String LARGE_TEST_FOLDER = "test-large-files/"; + private static FileClient largeFileClient; + private static String fileName; + private static File largeFile; + private ShareClient shareClient; + private File dirPath; + + @Rule + public TestName testName = new TestName(); + + @Before + public void setup() { + assumeTrue("The test is only for live mode.", FileTestHelpers.getTestMode() == TestMode.RECORD); + fileName = testResourceNamer.randomName("largefile", 16); + URL folderUrl = LargeFileTest.class.getClassLoader().getResource("."); + dirPath = new File(folderUrl.getPath() + LARGE_TEST_FOLDER); + if (dirPath.exists() || dirPath.mkdir()) { + largeFile = new File(folderUrl.getPath() + LARGE_TEST_FOLDER + fileName); + } else { + largeFileLogger.asWarning().log("Failed to create the large file dir."); + } + String shareName = testResourceNamer.randomName("largefileshare", 32); + shareClient = new ShareClientBuilder().connectionString(azureStorageConnectionString).shareName(shareName) + .buildClient(); + shareClient.create(); + shareClient.createDirectory("largefiledir"); + largeFileClient = shareClient.getDirectoryClient("largefiledir").getFileClient(fileName); + } + + @Ignore + @Test + public void uploadAndDownloadLargeFile() throws Exception { + Long fileSize = 5 * 1024 * 1024L; + RandomAccessFile raf = new RandomAccessFile(largeFile, "rw"); + raf.setLength(fileSize); + largeFileClient.create(fileSize); + if (largeFile.exists()) { + largeFileClient.uploadFromFile(largeFile.getPath()); + largeFileLogger.asWarning().log("Uploaded success!"); + } else { + fail("Did not find the upload file."); + } + OffsetDateTime start = OffsetDateTime.now(); + File downloadFile = new File(dirPath + "/" + testResourceNamer.randomName("download", 16)); + downloadFile.createNewFile(); + largeFileClient.downloadToFile(downloadFile.getPath()); + System.out.println("Download " + downloadFile.length() + " bytes took " + Duration.between(start, OffsetDateTime.now()).getSeconds() + " seconds"); + if (Files.exists(downloadFile.toPath()) && Files.exists(largeFile.toPath())) { + String checksumUpload = getFileChecksum(largeFile); + String checksumDownload = getFileChecksum(downloadFile); + Assert.assertEquals(checksumUpload, checksumDownload); + } else { + fail("Did not find the download file."); + } + } + + @After + public void cleanUp() { + assumeTrue("The test is only for live mode.", FileTestHelpers.getTestMode() == TestMode.RECORD); + shareClient.delete(); + FileTestHelpers.sleepInRecordMode(Duration.ofSeconds(45)); + } + + private String getFileChecksum(File file) throws Exception { + MessageDigest md = MessageDigest.getInstance("MD5"); + md.update(Files.readAllBytes(file.toPath())); + int numRead; + InputStream fis = new FileInputStream(file.getPath()); + byte[] buffer = new byte[1024]; + do { + numRead = fis.read(buffer); + if (numRead > 0) { + md.update(buffer, 0, numRead); + } + } while (numRead != -1); + + fis.close(); + byte[] digestByte = md.digest(); + String result = ""; + for (int i = 0; i < digestByte.length; i++) { + result += Integer.toString((digestByte[i] & 0xff) + 0x100, 16).substring(1); + } + return result; + } + + /** + * Gets the name of the current test being run. + *

                  + * NOTE: This could not be implemented in the base class using {@link TestName} because it always returns {@code + * null}. See https://stackoverflow.com/a/16113631/4220757. + * + * @return The name of the current test. + */ + @Override + protected String testName() { + return testName.getMethodName(); + } +} diff --git a/storage/client/file/src/test/java/com/azure/storage/file/ShareAsyncClientTests.java b/storage/client/file/src/test/java/com/azure/storage/file/ShareAsyncClientTests.java new file mode 100644 index 0000000000000..d98273108b491 --- /dev/null +++ b/storage/client/file/src/test/java/com/azure/storage/file/ShareAsyncClientTests.java @@ -0,0 +1,618 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.storage.file; + +import com.azure.core.http.HttpClient; +import com.azure.core.http.policy.HttpLogDetailLevel; +import com.azure.core.http.rest.Response; +import com.azure.core.util.logging.ClientLogger; +import com.azure.storage.file.models.AccessPolicy; +import com.azure.storage.file.models.ShareSnapshotInfo; +import com.azure.storage.file.models.SignedIdentifier; +import com.azure.storage.file.models.StorageErrorException; +import java.time.Duration; +import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import org.junit.Assert; +import reactor.test.StepVerifier; + +import static com.azure.storage.file.FileTestHelpers.createShareClientWithSnapshot; +import static com.azure.storage.file.FileTestHelpers.setupClient; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class ShareAsyncClientTests extends ShareClientTestBase { + private final ClientLogger shareAsyncLogger = new ClientLogger(ShareAsyncClientTests.class); + + private ShareAsyncClient shareAsyncClient; + + @Override + public void beforeTest() { + shareName = getShareName(); + + if (interceptorManager.isPlaybackMode()) { + shareAsyncClient = setupClient((connectionString, endpoint) -> new ShareClientBuilder() + .connectionString(connectionString) + .endpoint(endpoint) + .shareName(shareName) + .httpClient(interceptorManager.getPlaybackClient()) + .httpLogDetailLevel(HttpLogDetailLevel.BODY_AND_HEADERS) + .buildAsyncClient(), true, shareAsyncLogger); + } else { + shareAsyncClient = setupClient((connectionString, endpoint) -> new ShareClientBuilder() + .connectionString(connectionString) + .endpoint(endpoint) + .shareName(shareName) + .httpClient(HttpClient.createDefault().wiretap(true)) + .httpLogDetailLevel(HttpLogDetailLevel.BODY_AND_HEADERS) + .addPolicy(interceptorManager.getRecordPolicy()) + .buildAsyncClient(), false, shareAsyncLogger); + } + } + + @Override + public void afterTest() { + try { + shareAsyncClient.delete().block(); + } catch (StorageErrorException ex) { + // Ignore the exception as the share is already deleted and that is what we wanted. + } + } + + @Override + public void getRootDirectoryDoesNotCreateADirectory() { + shareAsyncClient.create().block(); + DirectoryAsyncClient directoryAsyncClient = shareAsyncClient.getRootDirectoryClient(); + StepVerifier.create(directoryAsyncClient.getProperties()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 200)) + .verifyComplete(); + } + + @Override + public void getDirectoryDoesNotCreateADirectory() { + shareAsyncClient.create().block(); + DirectoryAsyncClient directoryAsyncClient = shareAsyncClient.getDirectoryClient("testshare"); + Assert.assertNotNull(directoryAsyncClient); + StepVerifier.create(directoryAsyncClient.getProperties()) + .verifyErrorSatisfies(response -> FileTestHelpers.assertExceptionStatusCode(response, 404)); + } + + @Override + public void createDirectoryFromShareClient() { + shareAsyncClient.create().block(); + StepVerifier.create(shareAsyncClient.createDirectory("testshare")) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + } + + @Override + public void createDirectoryInvalidNameFromShareClient() { + shareAsyncClient.create().block(); + StepVerifier.create(shareAsyncClient.createDirectory("test/share")) + .verifyErrorSatisfies(response -> FileTestHelpers.assertExceptionStatusCode(response, 404)); + } + + @Override + public void createDirectoryAlreadyExistsFromShareClient() { + shareAsyncClient.create().block(); + shareAsyncClient.createDirectory("testshare").block(); + StepVerifier.create(shareAsyncClient.createDirectory("testshare")) + .verifyErrorSatisfies(response -> FileTestHelpers.assertExceptionStatusCode(response, 409)); + } + + @Override + public void deleteDirectoryFromShareClient() { + shareAsyncClient.create().block(); + shareAsyncClient.createDirectory("testshare").block(); + StepVerifier.create(shareAsyncClient.deleteDirectory("testshare")) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 202)) + .verifyComplete(); + } + + @Override + public void deleteDirectoryDoesNotExistFromShareClient() { + shareAsyncClient.create().block(); + StepVerifier.create(shareAsyncClient.deleteDirectory("testshare")) + .verifyErrorSatisfies(response -> FileTestHelpers.assertExceptionStatusCode(response, 404)); + } + + @Override + public void createFromShareClient() { + StepVerifier.create(shareAsyncClient.create()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + } + + @Override + public void createTwiceSameMetadataFromShareClient() { + Map metadata = Collections.singletonMap("test", "metadata"); + + StepVerifier.create(shareAsyncClient.create(metadata, 2)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(shareAsyncClient.create(metadata, 2)) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 409)); + } + + @Override + public void createTwiceDifferentMetadataFromShareClient() { + Map metadata = Collections.singletonMap("test", "metadata"); + + StepVerifier.create(shareAsyncClient.create()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(shareAsyncClient.create(metadata, 2)) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 409)); + } + + @Override + public void createInvalidQuotaFromShareClient() { + StepVerifier.create(shareAsyncClient.create(null, -1)) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 400)); + + StepVerifier.create(shareAsyncClient.create(null, 0)) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 400)); + } + + @Override + public void deleteFromShareClient() { + StepVerifier.create(shareAsyncClient.create()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(shareAsyncClient.delete()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 202)) + .verifyComplete(); + } + + @Override + public void deleteDoesNotExistFromShareClient() { + StepVerifier.create(shareAsyncClient.delete()) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 404)); + } + + @Override + public void deleteThenCreateFromShareClient() { + StepVerifier.create(shareAsyncClient.create()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(shareAsyncClient.delete()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 202)) + .verifyComplete(); + + FileTestHelpers.sleepInRecordMode(Duration.ofSeconds(45)); + + StepVerifier.create(shareAsyncClient.create()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + } + + @Override + public void deleteThenCreateTooSoonFromShareClient() { + StepVerifier.create(shareAsyncClient.create()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(shareAsyncClient.delete()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 202)) + .verifyComplete(); + + StepVerifier.create(shareAsyncClient.create()) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 409)); + } + + @Override + public void snapshot() { + StepVerifier.create(shareAsyncClient.create()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(shareAsyncClient.createSnapshot()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + } + + @Override + public void deleteSnapshotFromShareClient() { + StepVerifier.create(shareAsyncClient.create()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + Response snapshotInfoResponse = shareAsyncClient.createSnapshot().block(); + assertNotNull(snapshotInfoResponse); + FileTestHelpers.assertResponseStatusCode(snapshotInfoResponse, 201); + + ShareAsyncClient shareAsyncClientWithSnapshot = createShareClientWithSnapshot( + interceptorManager, shareName, snapshotInfoResponse.value().snapshot()).buildAsyncClient(); + StepVerifier.create(shareAsyncClientWithSnapshot.delete()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 202)) + .verifyComplete(); + + StepVerifier.create(shareAsyncClient.createSnapshot()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + } + + @Override + public void snapshotSameMetadata() { + Map metadata = Collections.singletonMap("test", "metadata"); + + StepVerifier.create(shareAsyncClient.create(metadata, 2)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + Response snapshotInfoResponse = shareAsyncClient.createSnapshot(metadata).block(); + assertNotNull(snapshotInfoResponse); + FileTestHelpers.assertResponseStatusCode(snapshotInfoResponse, 201); + + ShareAsyncClient shareAsyncClientWithSnapshot = createShareClientWithSnapshot( + interceptorManager, shareName, snapshotInfoResponse.value().snapshot()).buildAsyncClient(); + StepVerifier.create(shareAsyncClientWithSnapshot.getProperties()) + .assertNext(response -> { + FileTestHelpers.assertResponseStatusCode(response, 200); + assertEquals(metadata, response.value().metadata()); + }) + .verifyComplete(); + } + + @Override + public void snapshotDifferentMetadata() { + Map createMetadata = Collections.singletonMap("create", "metadata"); + + StepVerifier.create(shareAsyncClient.create(createMetadata, 2)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + Map updateMetadata = Collections.singletonMap("update", "metadata"); + Response snapshotInfoResponse = shareAsyncClient.createSnapshot(updateMetadata).block(); + assertNotNull(snapshotInfoResponse); + FileTestHelpers.assertResponseStatusCode(snapshotInfoResponse, 201); + + StepVerifier.create(shareAsyncClient.getProperties()) + .assertNext(response -> { + FileTestHelpers.assertResponseStatusCode(response, 200); + assertEquals(createMetadata, response.value().metadata()); + }) + .verifyComplete(); + ShareAsyncClient shareAsyncClientWithSnapshot = createShareClientWithSnapshot(interceptorManager, + shareName, snapshotInfoResponse.value().snapshot()).buildAsyncClient(); + + StepVerifier.create(shareAsyncClientWithSnapshot.getProperties()) + .assertNext(response -> { + FileTestHelpers.assertResponseStatusCode(response, 200); + assertEquals(updateMetadata, response.value().metadata()); + }) + .verifyComplete(); + } + + @Override + public void snapshotDoesNotExist() { + StepVerifier.create(shareAsyncClient.createSnapshot()) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 404)); + } + + @Override + public void getPropertiesFromShareClient() { + final int quotaInGB = 2; + Map metadata = Collections.singletonMap("test", "metadata"); + + StepVerifier.create(shareAsyncClient.create(metadata, quotaInGB)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(shareAsyncClient.getProperties()) + .assertNext(response -> { + FileTestHelpers.assertResponseStatusCode(response, 200); + assertEquals(quotaInGB, response.value().quota()); + assertEquals(metadata, response.value().metadata()); + }) + .verifyComplete(); + } + + @Override + public void getSnapshotPropertiesFromShareClient() { + final int quotaInGB = 2; + Map snapshotMetadata = Collections.singletonMap("snapshot", "metadata"); + + StepVerifier.create(shareAsyncClient.create(null, quotaInGB)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + Response snapshotInfoResponse = shareAsyncClient.createSnapshot(snapshotMetadata).block(); + assertNotNull(snapshotInfoResponse); + FileTestHelpers.assertResponseStatusCode(snapshotInfoResponse, 201); + ShareAsyncClient shareAsyncClientWithSnapshot = createShareClientWithSnapshot(interceptorManager, + shareName, snapshotInfoResponse.value().snapshot()).buildAsyncClient(); + StepVerifier.create(shareAsyncClientWithSnapshot.getProperties()) + .assertNext(response -> { + FileTestHelpers.assertResponseStatusCode(response, 200); + assertEquals(quotaInGB, response.value().quota()); + assertEquals(snapshotMetadata, response.value().metadata()); + }) + .verifyComplete(); + } + + @Override + public void getPropertiesDoesNotExistFromShareClient() { + StepVerifier.create(shareAsyncClient.getProperties()) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 404)); + } + + @Override + public void getSnapshotPropertiesDoesNotExist() { + StepVerifier.create(shareAsyncClient.create()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + ShareAsyncClient shareAsyncClientWithSnapshot = createShareClientWithSnapshot(interceptorManager, + shareName, "snapshot").buildAsyncClient(); + StepVerifier.create(shareAsyncClientWithSnapshot.getProperties()) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 400)); + } + + @Override + public void setPropertiesFromShareClient() { + final int initialQuoteInGB = 2; + + StepVerifier.create(shareAsyncClient.create(null, initialQuoteInGB)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(shareAsyncClient.getProperties()) + .assertNext(response -> { + FileTestHelpers.assertResponseStatusCode(response, 200); + assertEquals(initialQuoteInGB, response.value().quota()); + }) + .verifyComplete(); + + final int updatedQuotaInGB = 4; + StepVerifier.create(shareAsyncClient.setQuota(updatedQuotaInGB)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 200)) + .verifyComplete(); + + StepVerifier.create(shareAsyncClient.getProperties()) + .assertNext(response -> { + FileTestHelpers.assertResponseStatusCode(response, 200); + assertEquals(updatedQuotaInGB, response.value().quota()); + }) + .verifyComplete(); + } + + @Override + public void setPropertiesInvalidQuotaFromShareClient() { + StepVerifier.create(shareAsyncClient.create()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(shareAsyncClient.setQuota(-1)) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 400)); + + StepVerifier.create(shareAsyncClient.setQuota(9999)) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 400)); + } + + @Override + public void setPropertiesDoesNotExistFromShareClient() { + StepVerifier.create(shareAsyncClient.setQuota(2)) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 404)); + } + + @Override + public void getMetadataFromShareClient() { + Map metadata = Collections.singletonMap("test", "metadata"); + StepVerifier.create(shareAsyncClient.create(metadata, 2)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(shareAsyncClient.getProperties()) + .assertNext(response -> { + FileTestHelpers.assertResponseStatusCode(response, 200); + assertEquals(metadata, response.value().metadata()); + }) + .verifyComplete(); + } + + @Override + public void getSnapshotMetadataFromShareClient() { + Map metadata = Collections.singletonMap("test", "metadata"); + StepVerifier.create(shareAsyncClient.create(metadata, 2)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + Response snapshotInfoResponse = shareAsyncClient.createSnapshot().block(); + assertNotNull(snapshotInfoResponse); + FileTestHelpers.assertResponseStatusCode(snapshotInfoResponse, 201); + + ShareAsyncClient shareAsyncClientWithSnapshot = createShareClientWithSnapshot(interceptorManager, + shareName, snapshotInfoResponse.value().snapshot()).buildAsyncClient(); + StepVerifier.create(shareAsyncClientWithSnapshot.getProperties()) + .assertNext(response -> { + FileTestHelpers.assertResponseStatusCode(response, 200); + assertEquals(metadata, response.value().metadata()); + }) + .verifyComplete(); + } + + @Override + public void getMetadataDoesNotExistFromShareClient() { + StepVerifier.create(shareAsyncClient.getProperties()) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 404)); + } + + @Override + public void getSnapshotMetadataDoesNotExistFromShareClient() { + StepVerifier.create(shareAsyncClient.create()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + ShareAsyncClient shareAsyncClientWithSnapshot = createShareClientWithSnapshot(interceptorManager, + shareName, "snapshot").buildAsyncClient(); + StepVerifier.create(shareAsyncClientWithSnapshot.getProperties()) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 400)); + } + + @Override + public void setMetadataFromShareClient() { + StepVerifier.create(shareAsyncClient.create()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + Map metadata = Collections.singletonMap("setting", "metadata"); + StepVerifier.create(shareAsyncClient.setMetadata(metadata)) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 200)) + .verifyComplete(); + + StepVerifier.create(shareAsyncClient.getProperties()) + .assertNext(response -> { + FileTestHelpers.assertResponseStatusCode(response, 200); + assertEquals(metadata, response.value().metadata()); + }) + .verifyComplete(); + } + + @Override + public void setMetadataInvalidMetadataFromShareClient() { + StepVerifier.create(shareAsyncClient.create()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + Map metadata = Collections.singletonMap("", "metadata"); + StepVerifier.create(shareAsyncClient.setMetadata(metadata)) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 400)); + } + + @Override + public void setMetadataDoesNotExistFromShareClient() { + Map metadata = Collections.singletonMap("test", "metadata"); + StepVerifier.create(shareAsyncClient.setMetadata(metadata)) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 404)); + } + + @Override + public void getPolicies() { + StepVerifier.create(shareAsyncClient.create()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(shareAsyncClient.getAccessPolicy()) + .expectNextCount(0) + .verifyComplete(); + } + + @Override + public void getPoliciesDoesNotExist() { + StepVerifier.create(shareAsyncClient.getAccessPolicy()) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 404)); + } + + @Override + public void setPolicies() { + StepVerifier.create(shareAsyncClient.create()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + AccessPolicy policy = new AccessPolicy().permission("r") + .start(OffsetDateTime.of(LocalDateTime.of(2000, 1, 1, 0, 0), ZoneOffset.UTC)) + .expiry(OffsetDateTime.of(LocalDateTime.of(2020, 1, 1, 0, 0), ZoneOffset.UTC)); + + SignedIdentifier permission = new SignedIdentifier().id("test") + .accessPolicy(policy); + + StepVerifier.create(shareAsyncClient.setAccessPolicy(Collections.singletonList(permission))) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 200)) + .verifyComplete(); + + StepVerifier.create(shareAsyncClient.getAccessPolicy()) + .assertNext(responsePermission -> FileTestHelpers.assertPermissionsAreEqual(permission, responsePermission)) + .verifyComplete(); + } + + @Override + public void setPoliciesInvalidPermission() { + StepVerifier.create(shareAsyncClient.create()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + AccessPolicy policy = new AccessPolicy().permission("abcdefg") + .start(OffsetDateTime.of(LocalDateTime.of(2000, 1, 1, 0, 0), ZoneOffset.UTC)) + .expiry(OffsetDateTime.of(LocalDateTime.of(2020, 1, 1, 0, 0), ZoneOffset.UTC)); + + SignedIdentifier permission = new SignedIdentifier().id("test") + .accessPolicy(policy); + + StepVerifier.create(shareAsyncClient.setAccessPolicy(Collections.singletonList(permission))) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 400)); + } + + @Override + public void setPoliciesTooManyPermissions() { + StepVerifier.create(shareAsyncClient.create()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + List permissions = new ArrayList<>(); + for (int i = 0; i < 6; i++) { + AccessPolicy policy = new AccessPolicy().permission("r") + .start(OffsetDateTime.of(LocalDateTime.of(2000, 1, 1, 0, 0), ZoneOffset.UTC)) + .expiry(OffsetDateTime.of(LocalDateTime.of(2020, 1, 1, 0, 0), ZoneOffset.UTC)); + + permissions.add(new SignedIdentifier().id("test" + i).accessPolicy(policy)); + } + + StepVerifier.create(shareAsyncClient.setAccessPolicy(permissions)) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 400)); + } + + @Override + public void setPoliciesDoesNotExist() { + AccessPolicy policy = new AccessPolicy().permission("r") + .start(OffsetDateTime.of(LocalDateTime.of(2000, 1, 1, 0, 0), ZoneOffset.UTC)) + .expiry(OffsetDateTime.of(LocalDateTime.of(2020, 1, 1, 0, 0), ZoneOffset.UTC)); + + SignedIdentifier permission = new SignedIdentifier().id("test") + .accessPolicy(policy); + + StepVerifier.create(shareAsyncClient.setAccessPolicy(Collections.singletonList(permission))) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 404)); + } + + @Override + public void getStats() { + StepVerifier.create(shareAsyncClient.create()) + .assertNext(response -> FileTestHelpers.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(shareAsyncClient.getStatistics()) + .assertNext(response -> { + FileTestHelpers.assertResponseStatusCode(response, 200); + assertEquals(0, response.value().getShareUsageInGB()); + }) + .verifyComplete(); + } + + @Override + public void getStatsDoesNotExist() { + StepVerifier.create(shareAsyncClient.getStatistics()) + .verifyErrorSatisfies(throwable -> FileTestHelpers.assertExceptionStatusCode(throwable, 404)); + } + + @Override + public void getSnapshotId() { + shareAsyncClient.create().block(); + StepVerifier.create(shareAsyncClient.createSnapshot()) + .assertNext(response -> { + ShareAsyncClient shareAsyncClientWithSnapshot = createShareClientWithSnapshot(interceptorManager, + shareName, response.value().snapshot()).buildAsyncClient(); + Assert.assertEquals(response.value().snapshot(), shareAsyncClientWithSnapshot.getSnapshotId()); + }) + .verifyComplete(); + + } +} diff --git a/storage/client/file/src/test/java/com/azure/storage/file/ShareClientTestBase.java b/storage/client/file/src/test/java/com/azure/storage/file/ShareClientTestBase.java new file mode 100644 index 0000000000000..fd1d1b81206da --- /dev/null +++ b/storage/client/file/src/test/java/com/azure/storage/file/ShareClientTestBase.java @@ -0,0 +1,170 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.storage.file; + +import com.azure.core.test.TestBase; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.rules.TestName; + +public abstract class ShareClientTestBase extends TestBase { + String shareName; + + @Rule + public TestName testName = new TestName(); + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + /** + * Gets the name of the current test being run. + *

                  + * NOTE: This could not be implemented in the base class using {@link TestName} because it always returns {@code + * null}. See https://stackoverflow.com/a/16113631/4220757. + * + * @return The name of the current test. + */ + + @Override + public String testName() { + return testName.getMethodName(); + } + + String getShareName() { + return testResourceNamer.randomName("share", 16).toLowerCase(); + } + + @Test + public abstract void getRootDirectoryDoesNotCreateADirectory(); + + @Test + public abstract void getDirectoryDoesNotCreateADirectory(); + + @Test + public abstract void createDirectoryFromShareClient(); + + @Test + public abstract void createDirectoryInvalidNameFromShareClient(); + + @Test + public abstract void createDirectoryAlreadyExistsFromShareClient(); + + @Test + public abstract void deleteDirectoryFromShareClient(); + + @Test + public abstract void deleteDirectoryDoesNotExistFromShareClient(); + + @Test + public abstract void createFromShareClient(); + + @Test + public abstract void createTwiceSameMetadataFromShareClient(); + + @Test + public abstract void createTwiceDifferentMetadataFromShareClient(); + + @Test + public abstract void createInvalidQuotaFromShareClient(); + + @Test + public abstract void deleteFromShareClient(); + + @Test + public abstract void deleteDoesNotExistFromShareClient(); + + @Test + public abstract void deleteThenCreateFromShareClient(); + + /** + * Cannot re-create a share within 30 seconds of it being deleted. + */ + @Test + public abstract void deleteThenCreateTooSoonFromShareClient(); + + @Test + public abstract void snapshot(); + + @Test + public abstract void deleteSnapshotFromShareClient(); + + @Test + public abstract void snapshotSameMetadata(); + + @Test + public abstract void snapshotDifferentMetadata(); + + @Test + public abstract void snapshotDoesNotExist(); + + @Test + public abstract void getPropertiesFromShareClient(); + + @Test + public abstract void getSnapshotPropertiesFromShareClient(); + + @Test + public abstract void getPropertiesDoesNotExistFromShareClient(); + + @Test + public abstract void getSnapshotPropertiesDoesNotExist(); + + @Test + public abstract void setPropertiesFromShareClient(); + + @Test + public abstract void setPropertiesInvalidQuotaFromShareClient(); + + @Test + public abstract void setPropertiesDoesNotExistFromShareClient(); + + @Test + public abstract void getMetadataFromShareClient(); + + @Test + public abstract void getSnapshotMetadataFromShareClient(); + + @Test + public abstract void getMetadataDoesNotExistFromShareClient(); + + @Test + public abstract void getSnapshotMetadataDoesNotExistFromShareClient(); + + @Test + public abstract void setMetadataFromShareClient(); + + @Test + public abstract void setMetadataInvalidMetadataFromShareClient(); + + @Test + public abstract void setMetadataDoesNotExistFromShareClient(); + + @Test + public abstract void getPolicies(); + + @Test + public abstract void getPoliciesDoesNotExist(); + + @Test + public abstract void setPolicies(); + + @Test + public abstract void setPoliciesInvalidPermission(); + + @Test + public abstract void setPoliciesTooManyPermissions(); + + @Test + public abstract void setPoliciesDoesNotExist(); + + @Test + public abstract void getStats(); + + @Test + public abstract void getStatsDoesNotExist(); + + @Test + public abstract void getSnapshotId(); +} diff --git a/storage/client/file/src/test/java/com/azure/storage/file/ShareClientTests.java b/storage/client/file/src/test/java/com/azure/storage/file/ShareClientTests.java new file mode 100644 index 0000000000000..059d704630654 --- /dev/null +++ b/storage/client/file/src/test/java/com/azure/storage/file/ShareClientTests.java @@ -0,0 +1,490 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.storage.file; + +import com.azure.core.http.HttpClient; +import com.azure.core.http.policy.HttpLogDetailLevel; +import com.azure.core.http.rest.Response; +import com.azure.core.util.logging.ClientLogger; +import com.azure.storage.file.models.AccessPolicy; +import com.azure.storage.file.models.DirectoryProperties; +import com.azure.storage.file.models.ShareProperties; +import com.azure.storage.file.models.ShareSnapshotInfo; +import com.azure.storage.file.models.ShareStatistics; +import com.azure.storage.file.models.SignedIdentifier; +import com.azure.storage.file.models.StorageErrorException; +import java.time.Duration; +import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import org.junit.Assert; + +import static com.azure.storage.file.FileTestHelpers.createShareClientWithSnapshot; +import static com.azure.storage.file.FileTestHelpers.setupClient; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +public class ShareClientTests extends ShareClientTestBase { + private final ClientLogger shareLogger = new ClientLogger(ShareClient.class); + + private ShareClient shareClient; + + @Override + public void beforeTest() { + shareName = getShareName(); + + if (interceptorManager.isPlaybackMode()) { + shareClient = setupClient((connectionString, endpoint) -> new ShareClientBuilder() + .connectionString(connectionString) + .endpoint(endpoint) + .shareName(shareName) + .httpClient(interceptorManager.getPlaybackClient()) + .httpLogDetailLevel(HttpLogDetailLevel.BODY_AND_HEADERS) + .buildClient(), true, shareLogger); + } else { + shareClient = setupClient((connectionString, endpoint) -> new ShareClientBuilder() + .connectionString(connectionString) + .endpoint(endpoint) + .shareName(shareName) + .httpClient(HttpClient.createDefault().wiretap(true)) + .httpLogDetailLevel(HttpLogDetailLevel.BODY_AND_HEADERS) + .addPolicy(interceptorManager.getRecordPolicy()) + .buildClient(), false, shareLogger); + } + } + + @Override + public void afterTest() { + try { + shareClient.delete(); + } catch (StorageErrorException ex) { + // Ignore the exception as the share is already deleted and that is what we wanted. + } + } + + @Override + public void getRootDirectoryDoesNotCreateADirectory() { + shareClient.create(); + DirectoryClient directoryClient = shareClient.getRootDirectoryClient(); + Response response = directoryClient.getProperties(); + Assert.assertEquals(response.statusCode(), 200); + Assert.assertNotNull(response.value().eTag()); + } + + @Override + public void getDirectoryDoesNotCreateADirectory() { + shareClient.create(); + DirectoryClient directoryClient = shareClient.getDirectoryClient("testshare"); + Assert.assertNotNull(directoryClient); + thrown.expect(StorageErrorException.class); + thrown.expectMessage("ResourceNotFound"); + directoryClient.getProperties(); + } + + @Override + public void createDirectoryFromShareClient() { + shareClient.create(); + FileTestHelpers.assertResponseStatusCode(shareClient.createDirectory("testshare"), 201); + } + + @Override + public void createDirectoryInvalidNameFromShareClient() { + shareClient.create(); + thrown.expect(StorageErrorException.class); + thrown.expectMessage("ParentNotFound"); + shareClient.createDirectory("test/share"); + } + + @Override + public void createDirectoryAlreadyExistsFromShareClient() { + shareClient.create(); + shareClient.createDirectory("testshare"); + thrown.expect(StorageErrorException.class); + thrown.expectMessage("ResourceAlreadyExists"); + shareClient.createDirectory("testshare"); + } + + @Override + public void deleteDirectoryFromShareClient() { + shareClient.create(); + shareClient.createDirectory("testshare"); + FileTestHelpers.assertResponseStatusCode(shareClient.deleteDirectory("testshare"), 202); + } + + @Override + public void deleteDirectoryDoesNotExistFromShareClient() { + shareClient.create(); + thrown.expect(StorageErrorException.class); + thrown.expectMessage("ResourceNotFound"); + shareClient.deleteDirectory("testshare"); + } + + @Override + public void createFromShareClient() { + FileTestHelpers.assertResponseStatusCode(shareClient.create(), 201); + } + + @Override + public void createTwiceSameMetadataFromShareClient() { + Map metadata = Collections.singletonMap("test", "metadata"); + + FileTestHelpers.assertResponseStatusCode(shareClient.create(metadata, 2), 201); + + FileTestHelpers.assertExceptionStatusCode(() -> shareClient.create(metadata, 2), 409); + } + + @Override + public void createTwiceDifferentMetadataFromShareClient() { + Map metadata = Collections.singletonMap("test", "metadata"); + + FileTestHelpers.assertResponseStatusCode(shareClient.create(), 201); + + FileTestHelpers.assertExceptionStatusCode(() -> shareClient.create(metadata, 2), 409); + } + + @Override + public void createInvalidQuotaFromShareClient() { + FileTestHelpers.assertExceptionStatusCode(() -> shareClient.create(null, -1), 400); + + FileTestHelpers.assertExceptionStatusCode(() -> shareClient.create(null, 0), 400); + } + + @Override + public void deleteFromShareClient() { + FileTestHelpers.assertResponseStatusCode(shareClient.create(), 201); + + FileTestHelpers.assertResponseStatusCode(shareClient.delete(), 202); + } + + @Override + public void deleteDoesNotExistFromShareClient() { + FileTestHelpers.assertExceptionStatusCode(() -> shareClient.delete(), 404); + } + + @Override + public void deleteThenCreateFromShareClient() { + FileTestHelpers.assertResponseStatusCode(shareClient.create(), 201); + + FileTestHelpers.assertResponseStatusCode(shareClient.delete(), 202); + + FileTestHelpers.sleepInRecordMode(Duration.ofSeconds(45)); + + FileTestHelpers.assertResponseStatusCode(shareClient.create(), 201); + } + + @Override + public void deleteThenCreateTooSoonFromShareClient() { + FileTestHelpers.assertResponseStatusCode(shareClient.create(), 201); + + FileTestHelpers.assertResponseStatusCode(shareClient.delete(), 202); + + FileTestHelpers.assertExceptionStatusCode(() -> shareClient.create(), 409); + } + + @Override + public void snapshot() { + FileTestHelpers.assertResponseStatusCode(shareClient.create(), 201); + + FileTestHelpers.assertResponseStatusCode(shareClient.createSnapshot(), 201); + } + + @Override + public void deleteSnapshotFromShareClient() { + FileTestHelpers.assertResponseStatusCode(shareClient.create(), 201); + + Response snapshotInfoResponse = shareClient.createSnapshot(); + FileTestHelpers.assertResponseStatusCode(snapshotInfoResponse, 201); + + ShareClient shareClientWithSnapshot = createShareClientWithSnapshot(interceptorManager, shareName, + snapshotInfoResponse.value().snapshot()).buildClient(); + FileTestHelpers.assertResponseStatusCode(shareClientWithSnapshot.delete(), 202); + + FileTestHelpers.assertResponseStatusCode(shareClient.createSnapshot(), 201); + } + + @Override + public void snapshotSameMetadata() { + Map metadata = Collections.singletonMap("test", "metadata"); + + FileTestHelpers.assertResponseStatusCode(shareClient.create(metadata, 2), 201); + + Response snapshotInfoResponse = shareClient.createSnapshot(metadata); + FileTestHelpers.assertResponseStatusCode(snapshotInfoResponse, 201); + + ShareClient shareClientWithSnapshot = createShareClientWithSnapshot(interceptorManager, shareName, + snapshotInfoResponse.value().snapshot()).buildClient(); + Response propertiesResponse = shareClientWithSnapshot.getProperties(); + FileTestHelpers.assertResponseStatusCode(propertiesResponse, 200); + assertEquals(metadata, propertiesResponse.value().metadata()); + } + + @Override + public void snapshotDifferentMetadata() { + Map createMetadata = Collections.singletonMap("create", "metadata"); + + FileTestHelpers.assertResponseStatusCode(shareClient.create(createMetadata, 2), 201); + + Map updateMetadata = Collections.singletonMap("update", "metadata"); + Response snapshotInfoResponse = shareClient.createSnapshot(updateMetadata); + FileTestHelpers.assertResponseStatusCode(snapshotInfoResponse, 201); + + Response propertiesResponse = shareClient.getProperties(); + FileTestHelpers.assertResponseStatusCode(propertiesResponse, 200); + assertEquals(createMetadata, propertiesResponse.value().metadata()); + + ShareClient shareClientWithSnapshot = createShareClientWithSnapshot(interceptorManager, shareName, + snapshotInfoResponse.value().snapshot()).buildClient(); + propertiesResponse = shareClientWithSnapshot.getProperties(); + FileTestHelpers.assertResponseStatusCode(propertiesResponse, 200); + assertEquals(updateMetadata, propertiesResponse.value().metadata()); + } + + @Override + public void snapshotDoesNotExist() { + FileTestHelpers.assertExceptionStatusCode(() -> shareClient.createSnapshot(), 404); + } + + @Override + public void getPropertiesFromShareClient() { + final int quotaInGB = 2; + Map metadata = Collections.singletonMap("test", "metadata"); + + FileTestHelpers.assertResponseStatusCode(shareClient.create(metadata, quotaInGB), 201); + + Response propertiesResponse = shareClient.getProperties(); + FileTestHelpers.assertResponseStatusCode(propertiesResponse, 200); + assertEquals(quotaInGB, propertiesResponse.value().quota()); + assertEquals(metadata, propertiesResponse.value().metadata()); + } + + @Override + public void getSnapshotPropertiesFromShareClient() { + final int quotaInGB = 2; + Map snapshotMetadata = Collections.singletonMap("snapshot", "metadata"); + + FileTestHelpers.assertResponseStatusCode(shareClient.create(null, quotaInGB), 201); + + Response snapshotInfoResponse = shareClient.createSnapshot(snapshotMetadata); + FileTestHelpers.assertResponseStatusCode(snapshotInfoResponse, 201); + + ShareClient shareClientWithSnapshot = createShareClientWithSnapshot(interceptorManager, shareName, + snapshotInfoResponse.value().snapshot()).buildClient(); + Response propertiesResponse = shareClientWithSnapshot.getProperties(); + FileTestHelpers.assertResponseStatusCode(propertiesResponse, 200); + assertEquals(quotaInGB, propertiesResponse.value().quota()); + assertEquals(snapshotMetadata, propertiesResponse.value().metadata()); + } + + @Override + public void getPropertiesDoesNotExistFromShareClient() { + FileTestHelpers.assertExceptionStatusCode(() -> shareClient.getProperties(), 404); + } + + @Override + public void getSnapshotPropertiesDoesNotExist() { + FileTestHelpers.assertResponseStatusCode(shareClient.create(), 201); + + ShareClient shareClientWithSnapshot = createShareClientWithSnapshot(interceptorManager, shareName, + "snapshot").buildClient(); + FileTestHelpers.assertExceptionStatusCode(() -> shareClientWithSnapshot.getProperties(), 400); + } + + @Override + public void setPropertiesFromShareClient() { + final int initialQuoteInGB = 2; + + FileTestHelpers.assertResponseStatusCode(shareClient.create(null, initialQuoteInGB), 201); + + Response propertiesResponse = shareClient.getProperties(); + FileTestHelpers.assertResponseStatusCode(propertiesResponse, 200); + assertEquals(initialQuoteInGB, propertiesResponse.value().quota()); + + final int updatedQuotaInGB = 4; + FileTestHelpers.assertResponseStatusCode(shareClient.setQuota(updatedQuotaInGB), 200); + + propertiesResponse = shareClient.getProperties(); + FileTestHelpers.assertResponseStatusCode(propertiesResponse, 200); + assertEquals(updatedQuotaInGB, propertiesResponse.value().quota()); + } + + @Override + public void setPropertiesInvalidQuotaFromShareClient() { + FileTestHelpers.assertResponseStatusCode(shareClient.create(), 201); + + FileTestHelpers.assertExceptionStatusCode(() -> shareClient.setQuota(-1), 400); + FileTestHelpers.assertExceptionStatusCode(() -> shareClient.setQuota(9999), 400); + } + + @Override + public void setPropertiesDoesNotExistFromShareClient() { + FileTestHelpers.assertExceptionStatusCode(() -> shareClient.setQuota(2), 404); + } + + @Override + public void getMetadataFromShareClient() { + Map metadata = Collections.singletonMap("test", "metadata"); + FileTestHelpers.assertResponseStatusCode(shareClient.create(metadata, 2), 201); + + Response propertiesResponse = shareClient.getProperties(); + FileTestHelpers.assertResponseStatusCode(propertiesResponse, 200); + assertEquals(metadata, propertiesResponse.value().metadata()); + } + + @Override + public void getSnapshotMetadataFromShareClient() { + Map metadata = Collections.singletonMap("test", "metadata"); + + FileTestHelpers.assertResponseStatusCode(shareClient.create(metadata, 2), 201); + + Response snapshotInfoResponse = shareClient.createSnapshot(); + FileTestHelpers.assertResponseStatusCode(snapshotInfoResponse, 201); + + ShareClient shareClientWithSnapshot = createShareClientWithSnapshot(interceptorManager, shareName, + snapshotInfoResponse.value().snapshot()).buildClient(); + Response propertiesResponse = shareClientWithSnapshot.getProperties(); + FileTestHelpers.assertResponseStatusCode(propertiesResponse, 200); + assertEquals(metadata, propertiesResponse.value().metadata()); + } + + @Override + public void getMetadataDoesNotExistFromShareClient() { + FileTestHelpers.assertExceptionStatusCode(() -> shareClient.getProperties(), 404); + } + + @Override + public void getSnapshotMetadataDoesNotExistFromShareClient() { + FileTestHelpers.assertResponseStatusCode(shareClient.create(), 201); + + ShareClient shareClientWithSnapshot = createShareClientWithSnapshot(interceptorManager, shareName, + "snapshot").buildClient(); + FileTestHelpers.assertExceptionStatusCode(() -> shareClientWithSnapshot.getProperties(), 400); + } + + @Override + public void setMetadataFromShareClient() { + FileTestHelpers.assertResponseStatusCode(shareClient.create(), 201); + + Map metadata = Collections.singletonMap("setting", "metadata"); + FileTestHelpers.assertResponseStatusCode(shareClient.setMetadata(metadata), 200); + + Response propertiesResponse = shareClient.getProperties(); + FileTestHelpers.assertResponseStatusCode(propertiesResponse, 200); + assertEquals(metadata, propertiesResponse.value().metadata()); + } + + @Override + public void setMetadataInvalidMetadataFromShareClient() { + FileTestHelpers.assertResponseStatusCode(shareClient.create(), 201); + + Map metadata = Collections.singletonMap("", "metadata"); + FileTestHelpers.assertExceptionStatusCode(() -> shareClient.setMetadata(metadata), 400); + } + + @Override + public void setMetadataDoesNotExistFromShareClient() { + Map metadata = Collections.singletonMap("test", "metadata"); + FileTestHelpers.assertExceptionStatusCode(() -> shareClient.setMetadata(metadata), 404); + } + + @Override + public void getPolicies() { + FileTestHelpers.assertResponseStatusCode(shareClient.create(), 201); + + Iterator accessPolicies = shareClient.getAccessPolicy().iterator(); + assertFalse(accessPolicies.hasNext()); + } + + @Override + public void getPoliciesDoesNotExist() { + FileTestHelpers.assertExceptionStatusCode(() -> shareClient.getAccessPolicy().iterator().hasNext(), 404); + } + + @Override + public void setPolicies() { + FileTestHelpers.assertResponseStatusCode(shareClient.create(), 201); + + AccessPolicy policy = new AccessPolicy().permission("r") + .start(OffsetDateTime.of(LocalDateTime.of(2000, 1, 1, 0, 0), ZoneOffset.UTC)) + .expiry(OffsetDateTime.of(LocalDateTime.of(2020, 1, 1, 0, 0), ZoneOffset.UTC)); + + SignedIdentifier permission = new SignedIdentifier().id("test") + .accessPolicy(policy); + + FileTestHelpers.assertResponseStatusCode(shareClient.setAccessPolicy(Collections.singletonList(permission)), 200); + + Iterator permissions = shareClient.getAccessPolicy().iterator(); + FileTestHelpers.assertPermissionsAreEqual(permission, permissions.next()); + assertFalse(permissions.hasNext()); + } + + @Override + public void setPoliciesInvalidPermission() { + FileTestHelpers.assertResponseStatusCode(shareClient.create(), 201); + + AccessPolicy policy = new AccessPolicy().permission("abcdefg") + .start(OffsetDateTime.of(LocalDateTime.of(2000, 1, 1, 0, 0), ZoneOffset.UTC)) + .expiry(OffsetDateTime.of(LocalDateTime.of(2020, 1, 1, 0, 0), ZoneOffset.UTC)); + + SignedIdentifier permission = new SignedIdentifier().id("test") + .accessPolicy(policy); + + FileTestHelpers.assertExceptionStatusCode(() -> shareClient.setAccessPolicy(Collections.singletonList(permission)), 400); + } + + @Override + public void setPoliciesTooManyPermissions() { + FileTestHelpers.assertResponseStatusCode(shareClient.create(), 201); + + List permissions = new ArrayList<>(); + for (int i = 0; i < 6; i++) { + AccessPolicy policy = new AccessPolicy().permission("r") + .start(OffsetDateTime.of(LocalDateTime.of(2000, 1, 1, 0, 0), ZoneOffset.UTC)) + .expiry(OffsetDateTime.of(LocalDateTime.of(2020, 1, 1, 0, 0), ZoneOffset.UTC)); + + permissions.add(new SignedIdentifier().id("test" + i).accessPolicy(policy)); + } + + FileTestHelpers.assertExceptionStatusCode(() -> shareClient.setAccessPolicy(permissions), 400); + } + + @Override + public void setPoliciesDoesNotExist() { + AccessPolicy policy = new AccessPolicy().permission("r") + .start(OffsetDateTime.of(LocalDateTime.of(2000, 1, 1, 0, 0), ZoneOffset.UTC)) + .expiry(OffsetDateTime.of(LocalDateTime.of(2020, 1, 1, 0, 0), ZoneOffset.UTC)); + + SignedIdentifier permission = new SignedIdentifier().id("test") + .accessPolicy(policy); + + FileTestHelpers.assertExceptionStatusCode(() -> shareClient.setAccessPolicy(Collections.singletonList(permission)), 404); + } + + @Override + public void getStats() { + FileTestHelpers.assertResponseStatusCode(shareClient.create(), 201); + + Response statisticsResponse = shareClient.getStatistics(); + FileTestHelpers.assertResponseStatusCode(statisticsResponse, 200); + assertEquals(0, statisticsResponse.value().getShareUsageInGB()); + } + + @Override + public void getStatsDoesNotExist() { + FileTestHelpers.assertExceptionStatusCode(() -> shareClient.getStatistics(), 404); + } + + @Override + public void getSnapshotId() { + shareClient.create(); + String actualSnapshot = shareClient.createSnapshot().value().snapshot(); + ShareClient shareClientWithSnapshot = createShareClientWithSnapshot(interceptorManager, + shareName, actualSnapshot).buildClient(); + Assert.assertEquals(actualSnapshot, shareClientWithSnapshot.getSnapshotId()); + } +} diff --git a/storage/client/file/src/test/resources/session-records/abortCopy.json b/storage/client/file/src/test/resources/session-records/abortCopy.json new file mode 100644 index 0000000000000..44f4caf813585 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/abortCopy.json @@ -0,0 +1,4 @@ +{ + "networkCallRecords" : [ ], + "variables" : [ "file10519411" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/clearMetadataFromDirClient.json b/storage/client/file/src/test/resources/session-records/clearMetadataFromDirClient.json new file mode 100644 index 0000000000000..d9f06f7e804cf --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/clearMetadataFromDirClient.json @@ -0,0 +1,42 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory863334?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB67B1F98\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:12 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781ee1-001a-006b-3775-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:42:11 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory863334?restype=directory&comp=metadata", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB6831042\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:12 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781ee2-001a-006b-3875-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:42:11 GMT" + } + } ], + "variables" : [ "directory863334" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/createDirectoryAlreadyExistsFromShareClient.json b/storage/client/file/src/test/resources/session-records/createDirectoryAlreadyExistsFromShareClient.json new file mode 100644 index 0000000000000..ed9ad15510e4c --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/createDirectoryAlreadyExistsFromShareClient.json @@ -0,0 +1,76 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share22756b14?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C78DAADCB\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:29 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781d48-001a-006b-4875-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:28 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share22756b14/testshare?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C78E3B87F\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:29 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781d4a-001a-006b-4975-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:40:28 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share22756b14/testshare?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ResourceAlreadyExists", + "retry-after" : "0", + "Content-Length" : "228", + "StatusCode" : "409", + "x-ms-request-id" : "a4781d4b-001a-006b-4a75-4192c4000000", + "Body" : "ResourceAlreadyExistsThe specified resource already exists.\nRequestId:a4781d4b-001a-006b-4a75-4192c4000000\nTime:2019-07-23T16:40:29.4840714Z", + "Date" : "Tue, 23 Jul 2019 16:40:28 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share22756b14?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781d4c-001a-006b-4b75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:28 GMT" + } + } ], + "variables" : [ "share22756b14" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/createDirectoryFromShareClient.json b/storage/client/file/src/test/resources/session-records/createDirectoryFromShareClient.json new file mode 100644 index 0000000000000..b1e911a9b4d14 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/createDirectoryFromShareClient.json @@ -0,0 +1,57 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share2125750f?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C950469F4\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:41:16 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781dc0-001a-006b-7a75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:41:15 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share2125750f/testshare?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C950E2F68\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:41:16 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781dc2-001a-006b-7b75-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:41:15 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share2125750f?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781dc3-001a-006b-7c75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:41:16 GMT" + } + } ], + "variables" : [ "share2125750f" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/createDirectoryInvalidNameFromShareClient.json b/storage/client/file/src/test/resources/session-records/createDirectoryInvalidNameFromShareClient.json new file mode 100644 index 0000000000000..c1b5e624d12bb --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/createDirectoryInvalidNameFromShareClient.json @@ -0,0 +1,57 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share01242c86?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C76E38AFB\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:26 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781d01-001a-006b-1175-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:25 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share01242c86/test%2fshare?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ParentNotFound", + "retry-after" : "0", + "Content-Length" : "224", + "StatusCode" : "404", + "x-ms-request-id" : "a4781d03-001a-006b-1275-4192c4000000", + "Body" : "ParentNotFoundThe specified parent path does not exist.\nRequestId:a4781d03-001a-006b-1275-4192c4000000\nTime:2019-07-23T16:40:26.1306790Z", + "Date" : "Tue, 23 Jul 2019 16:40:25 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share01242c86?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781d04-001a-006b-1375-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:25 GMT" + } + } ], + "variables" : [ "share01242c86" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/createExcessMaxSizeFromFileClient.json b/storage/client/file/src/test/resources/session-records/createExcessMaxSizeFromFileClient.json new file mode 100644 index 0000000000000..4bb5ab15e2e22 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/createExcessMaxSizeFromFileClient.json @@ -0,0 +1,45 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/filesharename/testdir%2ffile6519698b", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C3EF47F55\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:38:52 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781c3b-001a-006b-4075-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:38:51 GMT" + } + }, { + "Method" : "HEAD", + "Uri" : "https://sima.file.core.windows.net/filesharename/testdir%2ffile6519698b", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "Last-Modified" : "Tue, 23 Jul 2019 16:38:52 GMT", + "retry-after" : "0", + "StatusCode" : "200", + "Date" : "Tue, 23 Jul 2019 16:38:51 GMT", + "x-ms-server-encrypted" : "true", + "x-ms-type" : "File", + "ETag" : "\"0x8D70F8C3EF47F55\"", + "Content-Length" : "0", + "x-ms-request-id" : "a4781c3c-001a-006b-4175-4192c4000000", + "Body" : "", + "Content-Type" : "application/octet-stream" + } + } ], + "variables" : [ "file6519698b" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/createFileFromDirClient.json b/storage/client/file/src/test/resources/session-records/createFileFromDirClient.json new file mode 100644 index 0000000000000..094a1138d065f --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/createFileFromDirClient.json @@ -0,0 +1,42 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory863163?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB576C6DE\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:11 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781ec3-001a-006b-1975-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:42:10 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory863163%2ftestfile", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB57F7AFF\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:11 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781ec4-001a-006b-1a75-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:42:10 GMT" + } + } ], + "variables" : [ "directory863163" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/createFileWithoutCreateDirFromDirClient.json b/storage/client/file/src/test/resources/session-records/createFileWithoutCreateDirFromDirClient.json new file mode 100644 index 0000000000000..0505db3315249 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/createFileWithoutCreateDirFromDirClient.json @@ -0,0 +1,23 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory886246%2ftestfile", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ParentNotFound", + "retry-after" : "0", + "Content-Length" : "224", + "StatusCode" : "404", + "x-ms-request-id" : "a4781ee0-001a-006b-3675-4192c4000000", + "Body" : "ParentNotFoundThe specified parent path does not exist.\nRequestId:a4781ee0-001a-006b-3675-4192c4000000\nTime:2019-07-23T16:42:12.6968560Z", + "Date" : "Tue, 23 Jul 2019 16:42:11 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "directory886246" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/createFromFileClient.json b/storage/client/file/src/test/resources/session-records/createFromFileClient.json new file mode 100644 index 0000000000000..2ae2af729c6b0 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/createFromFileClient.json @@ -0,0 +1,45 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/filesharename/testdir%2ffile91357575", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C3F05724F\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:38:52 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781c3d-001a-006b-4275-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:38:51 GMT" + } + }, { + "Method" : "HEAD", + "Uri" : "https://sima.file.core.windows.net/filesharename/testdir%2ffile91357575", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "Last-Modified" : "Tue, 23 Jul 2019 16:38:52 GMT", + "retry-after" : "0", + "StatusCode" : "200", + "Date" : "Tue, 23 Jul 2019 16:38:51 GMT", + "x-ms-server-encrypted" : "true", + "x-ms-type" : "File", + "ETag" : "\"0x8D70F8C3F05724F\"", + "Content-Length" : "1024", + "x-ms-request-id" : "a4781c3e-001a-006b-4375-4192c4000000", + "Body" : "", + "Content-Type" : "application/octet-stream" + } + } ], + "variables" : [ "file91357575" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/createFromShareClient.json b/storage/client/file/src/test/resources/session-records/createFromShareClient.json new file mode 100644 index 0000000000000..c802b0ddf43e0 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/createFromShareClient.json @@ -0,0 +1,38 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share923617a7?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C956279A2\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:41:17 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781dcc-001a-006b-0375-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:41:16 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share923617a7?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781dce-001a-006b-0475-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:41:16 GMT" + } + } ], + "variables" : [ "share923617a7" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/createInvalidQuotaFromShareClient.json b/storage/client/file/src/test/resources/session-records/createInvalidQuotaFromShareClient.json new file mode 100644 index 0000000000000..e6ca2bc82bca8 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/createInvalidQuotaFromShareClient.json @@ -0,0 +1,61 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share58139809?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "InvalidHeaderValue", + "retry-after" : "0", + "Content-Length" : "324", + "StatusCode" : "400", + "x-ms-request-id" : "a4781dac-001a-006b-6b75-4192c4000000", + "Body" : "InvalidHeaderValueThe value for one of the HTTP headers is not in the correct format.\nRequestId:a4781dac-001a-006b-6b75-4192c4000000\nTime:2019-07-23T16:41:15.7831129Zx-ms-share-quota-1", + "Date" : "Tue, 23 Jul 2019 16:41:15 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share58139809?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "InvalidHeaderValue", + "retry-after" : "0", + "Content-Length" : "323", + "StatusCode" : "400", + "x-ms-request-id" : "a4781dae-001a-006b-6c75-4192c4000000", + "Body" : "InvalidHeaderValueThe value for one of the HTTP headers is not in the correct format.\nRequestId:a4781dae-001a-006b-6c75-4192c4000000\nTime:2019-07-23T16:41:15.8301458Zx-ms-share-quota0", + "Date" : "Tue, 23 Jul 2019 16:41:15 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share58139809?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "a4781daf-001a-006b-6d75-4192c4000000", + "Body" : "ShareNotFoundThe specified share does not exist.\nRequestId:a4781daf-001a-006b-6d75-4192c4000000\nTime:2019-07-23T16:41:15.8781809Z", + "Date" : "Tue, 23 Jul 2019 16:41:15 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "share58139809" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/createMinFromDirClient.json b/storage/client/file/src/test/resources/session-records/createMinFromDirClient.json new file mode 100644 index 0000000000000..4a20dcab8864b --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/createMinFromDirClient.json @@ -0,0 +1,23 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory59046b?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB55B98CF\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:10 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781ec0-001a-006b-1675-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:42:10 GMT" + } + } ], + "variables" : [ "directory59046b" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/createShare.json b/storage/client/file/src/test/resources/session-records/createShare.json new file mode 100644 index 0000000000000..47eb2267cbd53 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/createShare.json @@ -0,0 +1,56 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share975192ac?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CED4EC679\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:43:44 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781f80-001a-006b-7075-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:43 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net?prefix=share975192ac&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781f82-001a-006b-7175-4192c4000000", + "Body" : "share975192acshare975192acTue, 23 Jul 2019 16:43:44 GMT\"0x8D70F8CED4EC679\"5120", + "Date" : "Tue, 23 Jul 2019 16:43:43 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share975192ac?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781f83-001a-006b-7275-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:43 GMT" + } + } ], + "variables" : [ "share975192ac" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/createShareInvalidQuota.json b/storage/client/file/src/test/resources/session-records/createShareInvalidQuota.json new file mode 100644 index 0000000000000..40109d33b40f6 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/createShareInvalidQuota.json @@ -0,0 +1,60 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share783156eb?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "InvalidHeaderValue", + "retry-after" : "0", + "Content-Length" : "324", + "StatusCode" : "400", + "x-ms-request-id" : "a4781f7b-001a-006b-6b75-4192c4000000", + "Body" : "InvalidHeaderValueThe value for one of the HTTP headers is not in the correct format.\nRequestId:a4781f7b-001a-006b-6b75-4192c4000000\nTime:2019-07-23T16:43:44.4843579Zx-ms-share-quota-1", + "Date" : "Tue, 23 Jul 2019 16:43:43 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share783156eb?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "InvalidHeaderValue", + "retry-after" : "0", + "Content-Length" : "329", + "StatusCode" : "400", + "x-ms-request-id" : "a4781f7c-001a-006b-6c75-4192c4000000", + "Body" : "InvalidHeaderValueThe value for one of the HTTP headers is not in the correct format.\nRequestId:a4781f7c-001a-006b-6c75-4192c4000000\nTime:2019-07-23T16:43:44.5303917Zx-ms-share-quota9999999", + "Date" : "Tue, 23 Jul 2019 16:43:43 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net?prefix=share783156eb&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781f7d-001a-006b-6d75-4192c4000000", + "Body" : "share783156eb", + "Date" : "Tue, 23 Jul 2019 16:43:43 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "share783156eb" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/createShareTwiceDifferentMetadata.json b/storage/client/file/src/test/resources/session-records/createShareTwiceDifferentMetadata.json new file mode 100644 index 0000000000000..d00c5e4cd4fbe --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/createShareTwiceDifferentMetadata.json @@ -0,0 +1,75 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share09717677?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CECAA2B0C\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:43:43 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781f67-001a-006b-5c75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:42 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share09717677?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareAlreadyExists", + "retry-after" : "0", + "Content-Length" : "222", + "StatusCode" : "409", + "x-ms-request-id" : "a4781f69-001a-006b-5d75-4192c4000000", + "Body" : "ShareAlreadyExistsThe specified share already exists.\nRequestId:a4781f69-001a-006b-5d75-4192c4000000\nTime:2019-07-23T16:43:43.7168101Z", + "Date" : "Tue, 23 Jul 2019 16:43:42 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net?prefix=share09717677&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781f6a-001a-006b-5e75-4192c4000000", + "Body" : "share09717677share09717677Tue, 23 Jul 2019 16:43:43 GMT\"0x8D70F8CECAA2B0C\"5120", + "Date" : "Tue, 23 Jul 2019 16:43:42 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share09717677?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781f6b-001a-006b-5f75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:42 GMT" + } + } ], + "variables" : [ "share09717677" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/createShareTwiceSameMetadata.json b/storage/client/file/src/test/resources/session-records/createShareTwiceSameMetadata.json new file mode 100644 index 0000000000000..d3959d887cd48 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/createShareTwiceSameMetadata.json @@ -0,0 +1,75 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share56293760?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CD18A473F\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:58 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781f17-001a-006b-4775-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:42:57 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share56293760?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareAlreadyExists", + "retry-after" : "0", + "Content-Length" : "222", + "StatusCode" : "409", + "x-ms-request-id" : "a4781f1a-001a-006b-4875-4192c4000000", + "Body" : "ShareAlreadyExistsThe specified share already exists.\nRequestId:a4781f1a-001a-006b-4875-4192c4000000\nTime:2019-07-23T16:42:58.2083345Z", + "Date" : "Tue, 23 Jul 2019 16:42:57 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net?prefix=share56293760&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781f1b-001a-006b-4975-4192c4000000", + "Body" : "share56293760share56293760Tue, 23 Jul 2019 16:42:58 GMT\"0x8D70F8CD18A473F\"5120", + "Date" : "Tue, 23 Jul 2019 16:42:57 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share56293760?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781f1c-001a-006b-4a75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:42:57 GMT" + } + } ], + "variables" : [ "share56293760" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/createSubDirectory.json b/storage/client/file/src/test/resources/session-records/createSubDirectory.json new file mode 100644 index 0000000000000..59d64ac3fbdc8 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/createSubDirectory.json @@ -0,0 +1,42 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory343921?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB5222EF0\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:10 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781eb8-001a-006b-1075-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:42:09 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory343921%2fdir0928634ae?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB529F881\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:10 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781eb9-001a-006b-1175-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:42:09 GMT" + } + } ], + "variables" : [ "directory343921", "dir0928634ae" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/createSubDirectoryTwiceSameMetadata.json b/storage/client/file/src/test/resources/session-records/createSubDirectoryTwiceSameMetadata.json new file mode 100644 index 0000000000000..a64488dace84c --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/createSubDirectoryTwiceSameMetadata.json @@ -0,0 +1,61 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory539316?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB658EB53\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:12 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781edd-001a-006b-3375-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:42:11 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory539316%2fdir505430058?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB6608DDA\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:12 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781ede-001a-006b-3475-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:42:11 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory539316%2fdir505430058?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ResourceAlreadyExists", + "retry-after" : "0", + "Content-Length" : "228", + "StatusCode" : "409", + "x-ms-request-id" : "a4781edf-001a-006b-3575-4192c4000000", + "Body" : "ResourceAlreadyExistsThe specified resource already exists.\nRequestId:a4781edf-001a-006b-3575-4192c4000000\nTime:2019-07-23T16:42:12.6388146Z", + "Date" : "Tue, 23 Jul 2019 16:42:11 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "directory539316", "dir505430058" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/createSubDirectoryWithMetadata.json b/storage/client/file/src/test/resources/session-records/createSubDirectoryWithMetadata.json new file mode 100644 index 0000000000000..f9f82666b5f61 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/createSubDirectoryWithMetadata.json @@ -0,0 +1,42 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory669858?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB6469886\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:12 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781edb-001a-006b-3175-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:42:11 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory669858%2fdir2413813c3?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB64F73C5\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:12 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781edc-001a-006b-3275-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:42:11 GMT" + } + } ], + "variables" : [ "directory669858", "dir2413813c3" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/createTwiceDifferentMetadataFromShareClient.json b/storage/client/file/src/test/resources/session-records/createTwiceDifferentMetadataFromShareClient.json new file mode 100644 index 0000000000000..8aca8fa7be88d --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/createTwiceDifferentMetadataFromShareClient.json @@ -0,0 +1,57 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share09921d47?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C9625C67A\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:41:18 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781de7-001a-006b-1775-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:41:17 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share09921d47?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareAlreadyExists", + "retry-after" : "0", + "Content-Length" : "222", + "StatusCode" : "409", + "x-ms-request-id" : "a4781de9-001a-006b-1875-4192c4000000", + "Body" : "ShareAlreadyExistsThe specified share already exists.\nRequestId:a4781de9-001a-006b-1875-4192c4000000\nTime:2019-07-23T16:41:18.5641031Z", + "Date" : "Tue, 23 Jul 2019 16:41:17 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share09921d47?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781dea-001a-006b-1975-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:41:17 GMT" + } + } ], + "variables" : [ "share09921d47" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/createTwiceFromDirClient.json b/storage/client/file/src/test/resources/session-records/createTwiceFromDirClient.json new file mode 100644 index 0000000000000..e69c7f627159e --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/createTwiceFromDirClient.json @@ -0,0 +1,42 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory874061?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB5C6F129\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:11 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781ecc-001a-006b-2275-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:42:10 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory874061?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ResourceAlreadyExists", + "retry-after" : "0", + "Content-Length" : "228", + "StatusCode" : "409", + "x-ms-request-id" : "a4781ecd-001a-006b-2375-4192c4000000", + "Body" : "ResourceAlreadyExistsThe specified resource already exists.\nRequestId:a4781ecd-001a-006b-2375-4192c4000000\nTime:2019-07-23T16:42:11.6300936Z", + "Date" : "Tue, 23 Jul 2019 16:42:10 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "directory874061" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/createTwiceSameMetadataFromShareClient.json b/storage/client/file/src/test/resources/session-records/createTwiceSameMetadataFromShareClient.json new file mode 100644 index 0000000000000..eeb6b80df7382 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/createTwiceSameMetadataFromShareClient.json @@ -0,0 +1,57 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share097329d5?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C7955C0AA\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:30 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781d59-001a-006b-5575-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:29 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share097329d5?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareAlreadyExists", + "retry-after" : "0", + "Content-Length" : "222", + "StatusCode" : "409", + "x-ms-request-id" : "a4781d5b-001a-006b-5675-4192c4000000", + "Body" : "ShareAlreadyExistsThe specified share already exists.\nRequestId:a4781d5b-001a-006b-5675-4192c4000000\nTime:2019-07-23T16:40:30.2245998Z", + "Date" : "Tue, 23 Jul 2019 16:40:29 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share097329d5?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781d5c-001a-006b-5775-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:29 GMT" + } + } ], + "variables" : [ "share097329d5" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/createWithMetadataFromDirClient.json b/storage/client/file/src/test/resources/session-records/createWithMetadataFromDirClient.json new file mode 100644 index 0000000000000..7105baad63f9e --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/createWithMetadataFromDirClient.json @@ -0,0 +1,23 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory435036?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB50A5CCE\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:10 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781eb6-001a-006b-0e75-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:42:09 GMT" + } + } ], + "variables" : [ "directory435036" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/deleteDirectoryDoesNotExistFromShareClient.json b/storage/client/file/src/test/resources/session-records/deleteDirectoryDoesNotExistFromShareClient.json new file mode 100644 index 0000000000000..f75e1d0d2d188 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/deleteDirectoryDoesNotExistFromShareClient.json @@ -0,0 +1,57 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share439185d7?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C78A0A76D\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:28 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781d3f-001a-006b-4175-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:28 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share439185d7/testshare?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ResourceNotFound", + "retry-after" : "0", + "Content-Length" : "223", + "StatusCode" : "404", + "x-ms-request-id" : "a4781d41-001a-006b-4275-4192c4000000", + "Body" : "ResourceNotFoundThe specified resource does not exist.\nRequestId:a4781d41-001a-006b-4275-4192c4000000\nTime:2019-07-23T16:40:29.0387539Z", + "Date" : "Tue, 23 Jul 2019 16:40:28 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share439185d7?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781d42-001a-006b-4375-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:28 GMT" + } + } ], + "variables" : [ "share439185d7" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/deleteDirectoryFromShareClient.json b/storage/client/file/src/test/resources/session-records/deleteDirectoryFromShareClient.json new file mode 100644 index 0000000000000..dfc32b3d44f4b --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/deleteDirectoryFromShareClient.json @@ -0,0 +1,73 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share89717092?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C77583406\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:26 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781d12-001a-006b-1e75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:26 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share89717092/testshare?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C77605492\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:26 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781d14-001a-006b-1f75-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:40:26 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share89717092/testshare?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781d15-001a-006b-2075-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:26 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share89717092?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781d16-001a-006b-2175-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:26 GMT" + } + } ], + "variables" : [ "share89717092" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/deleteDoesNotExistFromShareClient.json b/storage/client/file/src/test/resources/session-records/deleteDoesNotExistFromShareClient.json new file mode 100644 index 0000000000000..a46553c998e03 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/deleteDoesNotExistFromShareClient.json @@ -0,0 +1,42 @@ +{ + "networkCallRecords" : [ { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share3115815a?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "a4781d24-001a-006b-2c75-4192c4000000", + "Body" : "ShareNotFoundThe specified share does not exist.\nRequestId:a4781d24-001a-006b-2c75-4192c4000000\nTime:2019-07-23T16:40:27.6797839Z", + "Date" : "Tue, 23 Jul 2019 16:40:27 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share3115815a?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "a4781d25-001a-006b-2d75-4192c4000000", + "Body" : "ShareNotFoundThe specified share does not exist.\nRequestId:a4781d25-001a-006b-2d75-4192c4000000\nTime:2019-07-23T16:40:27.7278190Z", + "Date" : "Tue, 23 Jul 2019 16:40:27 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "share3115815a" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/deleteFileFromDirClient.json b/storage/client/file/src/test/resources/session-records/deleteFileFromDirClient.json new file mode 100644 index 0000000000000..3adb5ab423fe4 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/deleteFileFromDirClient.json @@ -0,0 +1,58 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory626180?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB68C1295\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:12 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781ee3-001a-006b-3975-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:42:12 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory626180%2ftestfile", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB697D48C\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:12 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781ee5-001a-006b-3a75-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:42:12 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory626180%2ftestfile", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781ee6-001a-006b-3b75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:42:12 GMT" + } + } ], + "variables" : [ "directory626180" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/deleteFileWithoutCreateFileFromDirClient.json b/storage/client/file/src/test/resources/session-records/deleteFileWithoutCreateFileFromDirClient.json new file mode 100644 index 0000000000000..3c115479ceb8d --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/deleteFileWithoutCreateFileFromDirClient.json @@ -0,0 +1,42 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory07934d?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB5B64C58\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:11 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781eca-001a-006b-2075-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:42:10 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory07934d%2ftestfile", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ResourceNotFound", + "retry-after" : "0", + "Content-Length" : "223", + "StatusCode" : "404", + "x-ms-request-id" : "a4781ecb-001a-006b-2175-4192c4000000", + "Body" : "ResourceNotFoundThe specified resource does not exist.\nRequestId:a4781ecb-001a-006b-2175-4192c4000000\nTime:2019-07-23T16:42:11.5220165Z", + "Date" : "Tue, 23 Jul 2019 16:42:10 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "directory07934d" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/deleteFromDirClient.json b/storage/client/file/src/test/resources/session-records/deleteFromDirClient.json new file mode 100644 index 0000000000000..a8a76a8698efa --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/deleteFromDirClient.json @@ -0,0 +1,39 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory046037?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB5A1FD55\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:11 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781ec8-001a-006b-1e75-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:42:10 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory046037?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781ec9-001a-006b-1f75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:42:10 GMT" + } + } ], + "variables" : [ "directory046037" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/deleteFromFileClient.json b/storage/client/file/src/test/resources/session-records/deleteFromFileClient.json new file mode 100644 index 0000000000000..cffa83f7633a6 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/deleteFromFileClient.json @@ -0,0 +1,39 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/filesharename/testdir%2ffile29223793", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C3DE92082\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:38:50 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781c23-001a-006b-2975-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:38:49 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/filesharename/testdir%2ffile29223793", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781c24-001a-006b-2a75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:38:50 GMT" + } + } ], + "variables" : [ "file29223793" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/deleteFromShareClient.json b/storage/client/file/src/test/resources/session-records/deleteFromShareClient.json new file mode 100644 index 0000000000000..53a92388620c4 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/deleteFromShareClient.json @@ -0,0 +1,57 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share5654566a?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C954995E4\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:41:17 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781dc8-001a-006b-8075-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:41:16 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share5654566a?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781dca-001a-006b-0175-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:41:16 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share5654566a?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareBeingDeleted", + "retry-after" : "0", + "Content-Length" : "244", + "StatusCode" : "409", + "x-ms-request-id" : "a4781dcb-001a-006b-0275-4192c4000000", + "Body" : "ShareBeingDeletedThe specified share is being deleted. Try operation later.\nRequestId:a4781dcb-001a-006b-0275-4192c4000000\nTime:2019-07-23T16:41:17.1721039Z", + "Date" : "Tue, 23 Jul 2019 16:41:16 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "share5654566a" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/deleteNotExistFromDirClient.json b/storage/client/file/src/test/resources/session-records/deleteNotExistFromDirClient.json new file mode 100644 index 0000000000000..25e82ae32c1ad --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/deleteNotExistFromDirClient.json @@ -0,0 +1,23 @@ +{ + "networkCallRecords" : [ { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory41395a?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ResourceNotFound", + "retry-after" : "0", + "Content-Length" : "223", + "StatusCode" : "404", + "x-ms-request-id" : "a4781eb7-001a-006b-0f75-4192c4000000", + "Body" : "ResourceNotFoundThe specified resource does not exist.\nRequestId:a4781eb7-001a-006b-0f75-4192c4000000\nTime:2019-07-23T16:42:10.4402453Z", + "Date" : "Tue, 23 Jul 2019 16:42:09 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "directory41395a" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/deleteShare.json b/storage/client/file/src/test/resources/session-records/deleteShare.json new file mode 100644 index 0000000000000..89ea9be57e9e9 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/deleteShare.json @@ -0,0 +1,56 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share18053aa4?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CED0E7D6D\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:43:44 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781f77-001a-006b-6875-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:43 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share18053aa4?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781f79-001a-006b-6975-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:43 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net?prefix=share18053aa4&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781f7a-001a-006b-6a75-4192c4000000", + "Body" : "share18053aa4", + "Date" : "Tue, 23 Jul 2019 16:43:43 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "share18053aa4" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/deleteShareDoesNotExist.json b/storage/client/file/src/test/resources/session-records/deleteShareDoesNotExist.json new file mode 100644 index 0000000000000..b4eb91ed496b4 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/deleteShareDoesNotExist.json @@ -0,0 +1,41 @@ +{ + "networkCallRecords" : [ { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share60248f77?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "a4781f91-001a-006b-7d75-4192c4000000", + "Body" : "ShareNotFoundThe specified share does not exist.\nRequestId:a4781f91-001a-006b-7d75-4192c4000000\nTime:2019-07-23T16:43:45.5241000Z", + "Date" : "Tue, 23 Jul 2019 16:43:44 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net?prefix=share60248f77&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781f92-001a-006b-7e75-4192c4000000", + "Body" : "share60248f77", + "Date" : "Tue, 23 Jul 2019 16:43:44 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "share60248f77" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/deleteSnapshotFromShareClient.json b/storage/client/file/src/test/resources/session-records/deleteSnapshotFromShareClient.json new file mode 100644 index 0000000000000..af124b98d68ab --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/deleteSnapshotFromShareClient.json @@ -0,0 +1,95 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share14317636?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C78330487\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:28 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781d31-001a-006b-3675-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:27 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share14317636?restype=share&comp=snapshot", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "x-ms-snapshot" : "2019-07-23T16:40:28.0000000Z", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C78330487\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:28 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781d33-001a-006b-3775-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:27 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share14317636?sharesnapshot=2019-07-23T16%3a40%3a28.0000000Z&restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "3975b159-b01a-003d-1975-417ab4000000", + "Date" : "Tue, 23 Jul 2019 16:40:27 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share14317636?restype=share&comp=snapshot", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "x-ms-snapshot" : "2019-07-23T16:40:28.0000000Z", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C78330487\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:28 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781d34-001a-006b-3875-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:27 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share14317636?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareHasSnapshots", + "retry-after" : "0", + "Content-Length" : "250", + "StatusCode" : "409", + "x-ms-request-id" : "a4781d35-001a-006b-3975-4192c4000000", + "Body" : "ShareHasSnapshotsThe share has snapshots and the operation requires no snapshots.\nRequestId:a4781d35-001a-006b-3975-4192c4000000\nTime:2019-07-23T16:40:28.5564098Z", + "Date" : "Tue, 23 Jul 2019 16:40:27 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "share14317636" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/deleteSubDirectory.json b/storage/client/file/src/test/resources/session-records/deleteSubDirectory.json new file mode 100644 index 0000000000000..c1ee2fab26aeb --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/deleteSubDirectory.json @@ -0,0 +1,58 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory283117?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB588CB7C\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:11 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781ec5-001a-006b-1b75-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:42:10 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory283117%2fdir94734a771?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB5910A5F\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:11 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781ec6-001a-006b-1c75-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:42:10 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory283117%2fdir94734a771?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781ec7-001a-006b-1d75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:42:10 GMT" + } + } ], + "variables" : [ "directory283117", "dir94734a771" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/deleteThenCreateFromShareClient.json b/storage/client/file/src/test/resources/session-records/deleteThenCreateFromShareClient.json new file mode 100644 index 0000000000000..40b598a321a9a --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/deleteThenCreateFromShareClient.json @@ -0,0 +1,72 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share2914350c?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C798FEE18\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:30 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781d61-001a-006b-5b75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:29 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share2914350c?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781d64-001a-006b-5c75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:29 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share2914350c?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C9473F66D\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:41:15 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781da8-001a-006b-6975-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:41:14 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share2914350c?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781dab-001a-006b-6a75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:41:14 GMT" + } + } ], + "variables" : [ "share2914350c" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/deleteThenCreateShareFromFileServiceClient.json b/storage/client/file/src/test/resources/session-records/deleteThenCreateShareFromFileServiceClient.json new file mode 100644 index 0000000000000..f19d87aafb782 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/deleteThenCreateShareFromFileServiceClient.json @@ -0,0 +1,90 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share90775610?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CD1AACD7E\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:58 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781f1e-001a-006b-4b75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:42:57 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share90775610?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781f20-001a-006b-4c75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:42:57 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share90775610?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CEC8DC438\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:43:43 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781f62-001a-006b-5975-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:42 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net?prefix=share90775610&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781f65-001a-006b-5a75-4192c4000000", + "Body" : "share90775610share90775610Tue, 23 Jul 2019 16:43:43 GMT\"0x8D70F8CEC8DC438\"5120", + "Date" : "Tue, 23 Jul 2019 16:43:42 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share90775610?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781f66-001a-006b-5b75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:42 GMT" + } + } ], + "variables" : [ "share90775610" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/deleteThenCreateShareTooSoonFromFileServiceClient.json b/storage/client/file/src/test/resources/session-records/deleteThenCreateShareTooSoonFromFileServiceClient.json new file mode 100644 index 0000000000000..db37837c21d40 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/deleteThenCreateShareTooSoonFromFileServiceClient.json @@ -0,0 +1,75 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share18271560?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CEDD6ACE2\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:43:45 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781f93-001a-006b-7f75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:44 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share18271560?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781f95-001a-006b-8075-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:44 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share18271560?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareBeingDeleted", + "retry-after" : "0", + "Content-Length" : "244", + "StatusCode" : "409", + "x-ms-request-id" : "a4781f96-001a-006b-0175-4192c4000000", + "Body" : "ShareBeingDeletedThe specified share is being deleted. Try operation later.\nRequestId:a4781f96-001a-006b-0175-4192c4000000\nTime:2019-07-23T16:43:45.7392533Z", + "Date" : "Tue, 23 Jul 2019 16:43:44 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net?prefix=share18271560&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781f97-001a-006b-0275-4192c4000000", + "Body" : "share18271560", + "Date" : "Tue, 23 Jul 2019 16:43:44 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "share18271560" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/deleteThenCreateTooSoonFromShareClient.json b/storage/client/file/src/test/resources/session-records/deleteThenCreateTooSoonFromShareClient.json new file mode 100644 index 0000000000000..797a7a88f9656 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/deleteThenCreateTooSoonFromShareClient.json @@ -0,0 +1,76 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share5053509d?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C77B90350\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:27 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781d1f-001a-006b-2875-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:26 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share5053509d?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781d21-001a-006b-2975-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:26 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share5053509d?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareBeingDeleted", + "retry-after" : "0", + "Content-Length" : "244", + "StatusCode" : "409", + "x-ms-request-id" : "a4781d22-001a-006b-2a75-4192c4000000", + "Body" : "ShareBeingDeletedThe specified share is being deleted. Try operation later.\nRequestId:a4781d22-001a-006b-2a75-4192c4000000\nTime:2019-07-23T16:40:27.5717072Z", + "Date" : "Tue, 23 Jul 2019 16:40:26 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share5053509d?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareBeingDeleted", + "retry-after" : "0", + "Content-Length" : "244", + "StatusCode" : "409", + "x-ms-request-id" : "a4781d23-001a-006b-2b75-4192c4000000", + "Body" : "ShareBeingDeletedThe specified share is being deleted. Try operation later.\nRequestId:a4781d23-001a-006b-2b75-4192c4000000\nTime:2019-07-23T16:40:27.6207424Z", + "Date" : "Tue, 23 Jul 2019 16:40:26 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "share5053509d" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/downloadWithProperties.json b/storage/client/file/src/test/resources/session-records/downloadWithProperties.json new file mode 100644 index 0000000000000..3370a153ba34a --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/downloadWithProperties.json @@ -0,0 +1,46 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/filesharename/testdir%2ffile95252ec1", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C3EE16905\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:38:52 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781c39-001a-006b-3e75-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:38:51 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net/filesharename/testdir%2ffile95252ec1", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "Last-Modified" : "Tue, 23 Jul 2019 16:38:52 GMT", + "retry-after" : "0", + "StatusCode" : "200", + "Date" : "Tue, 23 Jul 2019 16:38:51 GMT", + "Accept-Ranges" : "bytes", + "x-ms-server-encrypted" : "true", + "x-ms-type" : "File", + "ETag" : "\"0x8D70F8C3EE16905\"", + "Content-Length" : "1024", + "x-ms-request-id" : "a4781c3a-001a-006b-3f75-4192c4000000", + "Body" : "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", + "Content-Type" : "application/octet-stream" + } + } ], + "variables" : [ "file95252ec1" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/forceCloseHandlesFromDirClient.json b/storage/client/file/src/test/resources/session-records/forceCloseHandlesFromDirClient.json new file mode 100644 index 0000000000000..c9591fdb93263 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/forceCloseHandlesFromDirClient.json @@ -0,0 +1,41 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory240914?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB633D07C\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:12 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781ed9-001a-006b-2f75-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:42:11 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory240914?comp=listhandles", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781eda-001a-006b-3075-4192c4000000", + "Body" : "", + "Date" : "Tue, 23 Jul 2019 16:42:11 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "directory240914" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/forceCloseHandlesFromFileClient.json b/storage/client/file/src/test/resources/session-records/forceCloseHandlesFromFileClient.json new file mode 100644 index 0000000000000..70454bdb9891a --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/forceCloseHandlesFromFileClient.json @@ -0,0 +1,41 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/filesharename/testdir%2ffile32781af7", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C3E9C6451\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:38:51 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781c31-001a-006b-3675-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:38:51 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net/filesharename/testdir%2ffile32781af7?maxresults=10&comp=listhandles", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781c32-001a-006b-3775-4192c4000000", + "Body" : "10", + "Date" : "Tue, 23 Jul 2019 16:38:51 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "file32781af7" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/getDirectoryDoesNotCreateADirectory.json b/storage/client/file/src/test/resources/session-records/getDirectoryDoesNotCreateADirectory.json new file mode 100644 index 0000000000000..4046d646879b5 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/getDirectoryDoesNotCreateADirectory.json @@ -0,0 +1,57 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share10876776?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C94C66B41\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:41:16 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781db7-001a-006b-7375-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:41:15 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net/share10876776/testshare?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ResourceNotFound", + "retry-after" : "0", + "Content-Length" : "223", + "StatusCode" : "404", + "x-ms-request-id" : "a4781db9-001a-006b-7475-4192c4000000", + "Body" : "ResourceNotFoundThe specified resource does not exist.\nRequestId:a4781db9-001a-006b-7475-4192c4000000\nTime:2019-07-23T16:41:16.2604523Z", + "Date" : "Tue, 23 Jul 2019 16:41:15 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share10876776?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781dba-001a-006b-7575-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:41:15 GMT" + } + } ], + "variables" : [ "share10876776" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/getFileClientFromDirClient.json b/storage/client/file/src/test/resources/session-records/getFileClientFromDirClient.json new file mode 100644 index 0000000000000..8fa3f19ff9cd4 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/getFileClientFromDirClient.json @@ -0,0 +1,4 @@ +{ + "networkCallRecords" : [ ], + "variables" : [ "directory877236", "96d7c3acc68d4acc" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/getHandlesFromDirClient.json b/storage/client/file/src/test/resources/session-records/getHandlesFromDirClient.json new file mode 100644 index 0000000000000..0b31e3f9121c8 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/getHandlesFromDirClient.json @@ -0,0 +1,4 @@ +{ + "networkCallRecords" : [ ], + "variables" : [ "directory12788e" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/getMetadataDoesNotExistFromShareClient.json b/storage/client/file/src/test/resources/session-records/getMetadataDoesNotExistFromShareClient.json new file mode 100644 index 0000000000000..f98ba99546d8c --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/getMetadataDoesNotExistFromShareClient.json @@ -0,0 +1,42 @@ +{ + "networkCallRecords" : [ { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net/share620248bc?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "a4781d1c-001a-006b-2675-4192c4000000", + "Body" : "ShareNotFoundThe specified share does not exist.\nRequestId:a4781d1c-001a-006b-2675-4192c4000000\nTime:2019-07-23T16:40:27.3515501Z", + "Date" : "Tue, 23 Jul 2019 16:40:26 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share620248bc?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "a4781d1e-001a-006b-2775-4192c4000000", + "Body" : "ShareNotFoundThe specified share does not exist.\nRequestId:a4781d1e-001a-006b-2775-4192c4000000\nTime:2019-07-23T16:40:27.4035872Z", + "Date" : "Tue, 23 Jul 2019 16:40:26 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "share620248bc" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/getMetadataFromShareClient.json b/storage/client/file/src/test/resources/session-records/getMetadataFromShareClient.json new file mode 100644 index 0000000000000..6f7501b7b4c18 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/getMetadataFromShareClient.json @@ -0,0 +1,60 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share14921607?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C7868C45C\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:28 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781d36-001a-006b-3a75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:27 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net/share14921607?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-meta-test" : "metadata", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:28 GMT", + "retry-after" : "0", + "StatusCode" : "200", + "Date" : "Tue, 23 Jul 2019 16:40:27 GMT", + "x-ms-has-legal-hold" : "false", + "x-ms-share-quota" : "2", + "ETag" : "\"0x8D70F8C7868C45C\"", + "x-ms-has-immutability-policy" : "false", + "Content-Length" : "0", + "x-ms-request-id" : "a4781d38-001a-006b-3b75-4192c4000000" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share14921607?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781d39-001a-006b-3c75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:28 GMT" + } + } ], + "variables" : [ "share14921607" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/getPolicies.json b/storage/client/file/src/test/resources/session-records/getPolicies.json new file mode 100644 index 0000000000000..18ca1b282ab69 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/getPolicies.json @@ -0,0 +1,58 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share62141b58?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C7725F74B\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:26 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781d0a-001a-006b-1875-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:25 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net/share62141b58?restype=share&comp=acl", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C7725F74B\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:26 GMT", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781d0c-001a-006b-1975-4192c4000000", + "Body" : "", + "Date" : "Tue, 23 Jul 2019 16:40:25 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share62141b58?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781d0d-001a-006b-1a75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:25 GMT" + } + } ], + "variables" : [ "share62141b58" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/getPoliciesDoesNotExist.json b/storage/client/file/src/test/resources/session-records/getPoliciesDoesNotExist.json new file mode 100644 index 0000000000000..7831055f2c6d1 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/getPoliciesDoesNotExist.json @@ -0,0 +1,42 @@ +{ + "networkCallRecords" : [ { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net/share03196264?restype=share&comp=acl", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "a4781cfe-001a-006b-0f75-4192c4000000", + "Body" : "ShareNotFoundThe specified share does not exist.\nRequestId:a4781cfe-001a-006b-0f75-4192c4000000\nTime:2019-07-23T16:40:25.9575562Z", + "Date" : "Tue, 23 Jul 2019 16:40:25 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share03196264?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "a4781d00-001a-006b-1075-4192c4000000", + "Body" : "ShareNotFoundThe specified share does not exist.\nRequestId:a4781d00-001a-006b-1075-4192c4000000\nTime:2019-07-23T16:40:26.0095929Z", + "Date" : "Tue, 23 Jul 2019 16:40:25 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "share03196264" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/getPropertiesDoesNotExistFromShareClient.json b/storage/client/file/src/test/resources/session-records/getPropertiesDoesNotExistFromShareClient.json new file mode 100644 index 0000000000000..c366d9279459f --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/getPropertiesDoesNotExistFromShareClient.json @@ -0,0 +1,42 @@ +{ + "networkCallRecords" : [ { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net/share31141b34?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "a4781dbd-001a-006b-7875-4192c4000000", + "Body" : "ShareNotFoundThe specified share does not exist.\nRequestId:a4781dbd-001a-006b-7875-4192c4000000\nTime:2019-07-23T16:41:16.4866141Z", + "Date" : "Tue, 23 Jul 2019 16:41:15 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share31141b34?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "a4781dbf-001a-006b-7975-4192c4000000", + "Body" : "ShareNotFoundThe specified share does not exist.\nRequestId:a4781dbf-001a-006b-7975-4192c4000000\nTime:2019-07-23T16:41:16.5346484Z", + "Date" : "Tue, 23 Jul 2019 16:41:15 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "share31141b34" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/getPropertiesFromDirClient.json b/storage/client/file/src/test/resources/session-records/getPropertiesFromDirClient.json new file mode 100644 index 0000000000000..5c8e80b286d06 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/getPropertiesFromDirClient.json @@ -0,0 +1,42 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory937333?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB566491E\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:10 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781ec1-001a-006b-1775-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:42:10 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory937333?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-server-encrypted" : "true", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB566491E\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:10 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781ec2-001a-006b-1875-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:42:10 GMT" + } + } ], + "variables" : [ "directory937333" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/getPropertiesFromFileClient.json b/storage/client/file/src/test/resources/session-records/getPropertiesFromFileClient.json new file mode 100644 index 0000000000000..34c88368bdd9e --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/getPropertiesFromFileClient.json @@ -0,0 +1,45 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/filesharename/testdir%2ffile66368470", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C3EBE716D\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:38:51 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781c35-001a-006b-3a75-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:38:51 GMT" + } + }, { + "Method" : "HEAD", + "Uri" : "https://sima.file.core.windows.net/filesharename/testdir%2ffile66368470", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "Last-Modified" : "Tue, 23 Jul 2019 16:38:51 GMT", + "retry-after" : "0", + "StatusCode" : "200", + "Date" : "Tue, 23 Jul 2019 16:38:51 GMT", + "x-ms-server-encrypted" : "true", + "x-ms-type" : "File", + "ETag" : "\"0x8D70F8C3EBE716D\"", + "Content-Length" : "1024", + "x-ms-request-id" : "a4781c36-001a-006b-3b75-4192c4000000", + "Body" : "", + "Content-Type" : "application/octet-stream" + } + } ], + "variables" : [ "file66368470" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/getPropertiesFromShareClient.json b/storage/client/file/src/test/resources/session-records/getPropertiesFromShareClient.json new file mode 100644 index 0000000000000..dc43fd0afb917 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/getPropertiesFromShareClient.json @@ -0,0 +1,60 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share19304121?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C796F40BC\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:30 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781d5d-001a-006b-5875-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:29 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net/share19304121?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-meta-test" : "metadata", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:30 GMT", + "retry-after" : "0", + "StatusCode" : "200", + "Date" : "Tue, 23 Jul 2019 16:40:29 GMT", + "x-ms-has-legal-hold" : "false", + "x-ms-share-quota" : "2", + "ETag" : "\"0x8D70F8C796F40BC\"", + "x-ms-has-immutability-policy" : "false", + "Content-Length" : "0", + "x-ms-request-id" : "a4781d5f-001a-006b-5975-4192c4000000" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share19304121?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781d60-001a-006b-5a75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:29 GMT" + } + } ], + "variables" : [ "share19304121" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/getRootDirectoryDoesNotCreateADirectory.json b/storage/client/file/src/test/resources/session-records/getRootDirectoryDoesNotCreateADirectory.json new file mode 100644 index 0000000000000..ecd4380eb4e78 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/getRootDirectoryDoesNotCreateADirectory.json @@ -0,0 +1,57 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share33794f21?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C9528C16E\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:41:16 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781dc4-001a-006b-7d75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:41:16 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net/share33794f21/?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-server-encrypted" : "false", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C953238AE\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:41:16 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781dc6-001a-006b-7e75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:41:16 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share33794f21?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781dc7-001a-006b-7f75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:41:16 GMT" + } + } ], + "variables" : [ "share33794f21" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/getShareDoesNotCreateAShare.json b/storage/client/file/src/test/resources/session-records/getShareDoesNotCreateAShare.json new file mode 100644 index 0000000000000..1b9367c3df656 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/getShareDoesNotCreateAShare.json @@ -0,0 +1,41 @@ +{ + "networkCallRecords" : [ { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net/share96662a2c?restype=share&comp=stats", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "a4781fa7-001a-006b-0d75-4192c4000000", + "Body" : "ShareNotFoundThe specified share does not exist.\nRequestId:a4781fa7-001a-006b-0d75-4192c4000000\nTime:2019-07-23T16:43:46.2786384Z", + "Date" : "Tue, 23 Jul 2019 16:43:45 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net?prefix=share96662a2c&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781fa9-001a-006b-0e75-4192c4000000", + "Body" : "share96662a2c", + "Date" : "Tue, 23 Jul 2019 16:43:45 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "share96662a2c" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/getSnapshotId.json b/storage/client/file/src/test/resources/session-records/getSnapshotId.json new file mode 100644 index 0000000000000..02715f00c488a --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/getSnapshotId.json @@ -0,0 +1,60 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share69666dbd?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C773F5043\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:26 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781d0e-001a-006b-1b75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:25 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share69666dbd?restype=share&comp=snapshot", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "x-ms-snapshot" : "2019-07-23T16:40:26.0000000Z", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C773F5043\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:26 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781d10-001a-006b-1c75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:26 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share69666dbd?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareHasSnapshots", + "retry-after" : "0", + "Content-Length" : "250", + "StatusCode" : "409", + "x-ms-request-id" : "a4781d11-001a-006b-1d75-4192c4000000", + "Body" : "ShareHasSnapshotsThe share has snapshots and the operation requires no snapshots.\nRequestId:a4781d11-001a-006b-1d75-4192c4000000\nTime:2019-07-23T16:40:26.7761389Z", + "Date" : "Tue, 23 Jul 2019 16:40:26 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "share69666dbd" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/getSnapshotMetadataDoesNotExistFromShareClient.json b/storage/client/file/src/test/resources/session-records/getSnapshotMetadataDoesNotExistFromShareClient.json new file mode 100644 index 0000000000000..b6fb1b9aab467 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/getSnapshotMetadataDoesNotExistFromShareClient.json @@ -0,0 +1,57 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share053068d6?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C79224B3F\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:29 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781d52-001a-006b-5075-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:29 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net/share053068d6?sharesnapshot=snapshot&restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "InvalidQueryParameterValue", + "retry-after" : "0", + "Content-Length" : "445", + "StatusCode" : "400", + "x-ms-request-id" : "3975b15b-b01a-003d-1a75-417ab4000000", + "Body" : "InvalidQueryParameterValueValue for one of the query parameters specified in the request URI is invalid.\nRequestId:3975b15b-b01a-003d-1a75-417ab4000000\nTime:2019-07-23T16:40:29.8874826ZsharesnapshotsnapshotMust be in the specific snapshot date time format.", + "Date" : "Tue, 23 Jul 2019 16:40:29 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share053068d6?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781d54-001a-006b-5175-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:29 GMT" + } + } ], + "variables" : [ "share053068d6" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/getSnapshotMetadataFromShareClient.json b/storage/client/file/src/test/resources/session-records/getSnapshotMetadataFromShareClient.json new file mode 100644 index 0000000000000..4b6cfa5a5c4ac --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/getSnapshotMetadataFromShareClient.json @@ -0,0 +1,82 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share31872175?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C78061FF3\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:27 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781d2c-001a-006b-3375-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:27 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share31872175?restype=share&comp=snapshot", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "x-ms-snapshot" : "2019-07-23T16:40:28.0000000Z", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C78061FF3\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:27 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781d2e-001a-006b-3475-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:27 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net/share31872175?sharesnapshot=2019-07-23T16%3a40%3a28.0000000Z&restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-meta-test" : "metadata", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:27 GMT", + "retry-after" : "0", + "StatusCode" : "200", + "Date" : "Tue, 23 Jul 2019 16:40:27 GMT", + "x-ms-has-legal-hold" : "false", + "x-ms-share-quota" : "2", + "ETag" : "\"0x8D70F8C78061FF3\"", + "x-ms-has-immutability-policy" : "false", + "Content-Length" : "0", + "x-ms-request-id" : "3975b156-b01a-003d-1875-417ab4000000" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share31872175?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareHasSnapshots", + "retry-after" : "0", + "Content-Length" : "250", + "StatusCode" : "409", + "x-ms-request-id" : "a4781d30-001a-006b-3575-4192c4000000", + "Body" : "ShareHasSnapshotsThe share has snapshots and the operation requires no snapshots.\nRequestId:a4781d30-001a-006b-3575-4192c4000000\nTime:2019-07-23T16:40:28.1841446Z", + "Date" : "Tue, 23 Jul 2019 16:40:27 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "share31872175" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/getSnapshotPropertiesDoesNotExist.json b/storage/client/file/src/test/resources/session-records/getSnapshotPropertiesDoesNotExist.json new file mode 100644 index 0000000000000..f2da43b8c1a4d --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/getSnapshotPropertiesDoesNotExist.json @@ -0,0 +1,57 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share29111ff1?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C9574301E\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:41:17 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781dcf-001a-006b-0575-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:41:16 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net/share29111ff1?sharesnapshot=snapshot&restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "InvalidQueryParameterValue", + "retry-after" : "0", + "Content-Length" : "445", + "StatusCode" : "400", + "x-ms-request-id" : "3975b18f-b01a-003d-2675-417ab4000000", + "Body" : "InvalidQueryParameterValueValue for one of the query parameters specified in the request URI is invalid.\nRequestId:3975b18f-b01a-003d-2675-417ab4000000\nTime:2019-07-23T16:41:17.4022825ZsharesnapshotsnapshotMust be in the specific snapshot date time format.", + "Date" : "Tue, 23 Jul 2019 16:41:16 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share29111ff1?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781dd1-001a-006b-0675-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:41:16 GMT" + } + } ], + "variables" : [ "share29111ff1" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/getSnapshotPropertiesFromShareClient.json b/storage/client/file/src/test/resources/session-records/getSnapshotPropertiesFromShareClient.json new file mode 100644 index 0000000000000..8cac81d604f3c --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/getSnapshotPropertiesFromShareClient.json @@ -0,0 +1,82 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share49629d81?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C9603B94A\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:41:18 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781de3-001a-006b-1475-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:41:17 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share49629d81?restype=share&comp=snapshot", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "x-ms-snapshot" : "2019-07-23T16:41:18.0000000Z", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C95D7CB00\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:41:18 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781de5-001a-006b-1575-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:41:17 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net/share49629d81?sharesnapshot=2019-07-23T16%3a41%3a18.0000000Z&restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-meta-snapshot" : "metadata", + "Last-Modified" : "Tue, 23 Jul 2019 16:41:18 GMT", + "retry-after" : "0", + "StatusCode" : "200", + "Date" : "Tue, 23 Jul 2019 16:41:17 GMT", + "x-ms-has-legal-hold" : "false", + "x-ms-share-quota" : "2", + "ETag" : "\"0x8D70F8C95D7CB00\"", + "x-ms-has-immutability-policy" : "false", + "Content-Length" : "0", + "x-ms-request-id" : "3975b194-b01a-003d-2875-417ab4000000" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share49629d81?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareHasSnapshots", + "retry-after" : "0", + "Content-Length" : "250", + "StatusCode" : "409", + "x-ms-request-id" : "a4781de6-001a-006b-1675-4192c4000000", + "Body" : "ShareHasSnapshotsThe share has snapshots and the operation requires no snapshots.\nRequestId:a4781de6-001a-006b-1675-4192c4000000\nTime:2019-07-23T16:41:18.4480203Z", + "Date" : "Tue, 23 Jul 2019 16:41:17 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "share49629d81" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/getStats.json b/storage/client/file/src/test/resources/session-records/getStats.json new file mode 100644 index 0000000000000..b4ecd38b1caf6 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/getStats.json @@ -0,0 +1,56 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share67188f15?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C963EAA38\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:41:18 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781deb-001a-006b-1a75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:41:17 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net/share67188f15?restype=share&comp=stats", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781ded-001a-006b-1b75-4192c4000000", + "Body" : "0", + "Date" : "Tue, 23 Jul 2019 16:41:17 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share67188f15?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781dee-001a-006b-1c75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:41:18 GMT" + } + } ], + "variables" : [ "share67188f15" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/getStatsDoesNotExist.json b/storage/client/file/src/test/resources/session-records/getStatsDoesNotExist.json new file mode 100644 index 0000000000000..97ecc310dd26f --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/getStatsDoesNotExist.json @@ -0,0 +1,42 @@ +{ + "networkCallRecords" : [ { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net/share840508c1?restype=share&comp=stats", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "a4781db4-001a-006b-7175-4192c4000000", + "Body" : "ShareNotFoundThe specified share does not exist.\nRequestId:a4781db4-001a-006b-7175-4192c4000000\nTime:2019-07-23T16:41:16.1013399Z", + "Date" : "Tue, 23 Jul 2019 16:41:15 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share840508c1?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "a4781db6-001a-006b-7275-4192c4000000", + "Body" : "ShareNotFoundThe specified share does not exist.\nRequestId:a4781db6-001a-006b-7275-4192c4000000\nTime:2019-07-23T16:41:16.1493733Z", + "Date" : "Tue, 23 Jul 2019 16:41:15 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "share840508c1" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/getSubDirectoryClient.json b/storage/client/file/src/test/resources/session-records/getSubDirectoryClient.json new file mode 100644 index 0000000000000..786a8d1614b5d --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/getSubDirectoryClient.json @@ -0,0 +1,4 @@ +{ + "networkCallRecords" : [ ], + "variables" : [ "directory092514" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/listFilesAndDirectoriesFromDirClient.json b/storage/client/file/src/test/resources/session-records/listFilesAndDirectoriesFromDirClient.json new file mode 100644 index 0000000000000..8102f80f00dd5 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/listFilesAndDirectoriesFromDirClient.json @@ -0,0 +1,212 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory601397?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB5D8325F\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:11 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781ece-001a-006b-2475-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:42:10 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory601397%2fdirectory6013970?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB5E04A24\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:11 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781ecf-001a-006b-2575-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:42:10 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory601397%2fsamelayer02223a0", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB5E83ACF\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:11 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781ed0-001a-006b-2675-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:42:10 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory601397%2fdirectory6013970%2fnextlayer57757b0", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB5F13D27\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:11 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781ed1-001a-006b-2775-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:42:11 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory601397%2fdirectory6013971?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB5F92DCE\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:11 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781ed2-001a-006b-2875-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:42:11 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory601397%2fsamelayer02223a01", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB6011E86\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:11 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781ed3-001a-006b-2975-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:42:11 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory601397%2fdirectory6013971%2fnextlayer57757b01", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB608E814\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:12 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781ed4-001a-006b-2a75-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:42:11 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory601397%2fdirectory6013972?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB610B1B3\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:12 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781ed5-001a-006b-2b75-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:42:11 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory601397%2fsamelayer02223a012", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB618F08D\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:12 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781ed6-001a-006b-2c75-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:42:11 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory601397%2fdirectory6013972%2fnextlayer57757b012", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB620BA31\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:12 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781ed7-001a-006b-2d75-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:42:11 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory601397?restype=directory&comp=list", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781ed8-001a-006b-2e75-4192c4000000", + "Body" : "directory6013970directory6013971directory6013972samelayer02223a01024samelayer02223a011024samelayer02223a0121024", + "Date" : "Tue, 23 Jul 2019 16:42:11 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "directory601397", "samelayer02223a", "nextlayer57757b" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/listHandlesFromFileClient.json b/storage/client/file/src/test/resources/session-records/listHandlesFromFileClient.json new file mode 100644 index 0000000000000..a8429ac169638 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/listHandlesFromFileClient.json @@ -0,0 +1,41 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/filesharename/testdir%2ffile80711456", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C3E02EEBF\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:38:50 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781c25-001a-006b-2b75-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:38:50 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net/filesharename/testdir%2ffile80711456?comp=listhandles", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781c27-001a-006b-2c75-4192c4000000", + "Body" : "", + "Date" : "Tue, 23 Jul 2019 16:38:50 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "file80711456" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/listRangesFromFileClient.json b/storage/client/file/src/test/resources/session-records/listRangesFromFileClient.json new file mode 100644 index 0000000000000..26f25a74de99f --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/listRangesFromFileClient.json @@ -0,0 +1,65 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/filesharename/testdir%2ffile053136bd", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C3E1408CE\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:38:50 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781c28-001a-006b-2d75-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:38:50 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/filesharename/testdir%2ffile053136bd?comp=range", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/octet-stream" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C3E1DCE9C\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:38:50 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781c29-001a-006b-2e75-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:38:50 GMT", + "Content-MD5" : "wh+Wm18D0z1D4E+PE252gg==" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net/filesharename/testdir%2ffile053136bd?comp=rangelist", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-content-length" : "512", + "ETag" : "\"0x8D70F8C3E1DCE9C\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:38:50 GMT", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781c2a-001a-006b-2f75-4192c4000000", + "Body" : "0511", + "Date" : "Tue, 23 Jul 2019 16:38:50 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "file053136bd" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/listShares.json b/storage/client/file/src/test/resources/session-records/listShares.json new file mode 100644 index 0000000000000..9b4198a90038a --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/listShares.json @@ -0,0 +1,142 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share334220300?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CEDF8BA1A\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:43:45 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781f99-001a-006b-0475-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:44 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share334220301?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CEE0083B4\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:43:45 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781f9c-001a-006b-0675-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:44 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share334220302?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CEE084D4E\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:43:45 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781f9f-001a-006b-0775-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:44 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net?prefix=share33422030&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781fa2-001a-006b-0875-4192c4000000", + "Body" : "share33422030share334220300Tue, 23 Jul 2019 16:43:45 GMT\"0x8D70F8CEDF8BA1A\"2share334220301Tue, 23 Jul 2019 16:43:45 GMT\"0x8D70F8CEE0083B4\"2share334220302Tue, 23 Jul 2019 16:43:45 GMT\"0x8D70F8CEE084D4E\"2", + "Date" : "Tue, 23 Jul 2019 16:43:45 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net?prefix=share33422030&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781fa3-001a-006b-0975-4192c4000000", + "Body" : "share33422030share334220300Tue, 23 Jul 2019 16:43:45 GMT\"0x8D70F8CEDF8BA1A\"2share334220301Tue, 23 Jul 2019 16:43:45 GMT\"0x8D70F8CEE0083B4\"2share334220302Tue, 23 Jul 2019 16:43:45 GMT\"0x8D70F8CEE084D4E\"2", + "Date" : "Tue, 23 Jul 2019 16:43:45 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share334220300?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781fa4-001a-006b-0a75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:45 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share334220301?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781fa5-001a-006b-0b75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:45 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share334220302?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781fa6-001a-006b-0c75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:45 GMT" + } + } ], + "variables" : [ "share33422030" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/listSharesIncludeMetadata.json b/storage/client/file/src/test/resources/session-records/listSharesIncludeMetadata.json new file mode 100644 index 0000000000000..74e4401568be0 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/listSharesIncludeMetadata.json @@ -0,0 +1,142 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share116742420?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CEEFF5D8E\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:43:47 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781fc4-001a-006b-2375-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:46 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share116742421?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CEF077557\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:43:47 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781fc6-001a-006b-2475-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:46 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share116742422?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CEF0F3EF5\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:43:47 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781fc8-001a-006b-2575-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:46 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net?prefix=share11674242&include=metadata&comp=list", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781fca-001a-006b-2675-4192c4000000", + "Body" : "share11674242share116742420Tue, 23 Jul 2019 16:43:47 GMT\"0x8D70F8CEEFF5D8E\"2metadatashare116742421Tue, 23 Jul 2019 16:43:47 GMT\"0x8D70F8CEF077557\"2share116742422Tue, 23 Jul 2019 16:43:47 GMT\"0x8D70F8CEF0F3EF5\"2metadata", + "Date" : "Tue, 23 Jul 2019 16:43:46 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net?prefix=share11674242&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781fcb-001a-006b-2775-4192c4000000", + "Body" : "share11674242share116742420Tue, 23 Jul 2019 16:43:47 GMT\"0x8D70F8CEEFF5D8E\"2share116742421Tue, 23 Jul 2019 16:43:47 GMT\"0x8D70F8CEF077557\"2share116742422Tue, 23 Jul 2019 16:43:47 GMT\"0x8D70F8CEF0F3EF5\"2", + "Date" : "Tue, 23 Jul 2019 16:43:46 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share116742420?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781fcc-001a-006b-2875-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:46 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share116742421?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781fcd-001a-006b-2975-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:46 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share116742422?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781fce-001a-006b-2a75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:46 GMT" + } + } ], + "variables" : [ "share11674242" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/listSharesIncludeMetadataAndSnapshots.json b/storage/client/file/src/test/resources/session-records/listSharesIncludeMetadataAndSnapshots.json new file mode 100644 index 0000000000000..fc52365263ae3 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/listSharesIncludeMetadataAndSnapshots.json @@ -0,0 +1,186 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share112342ce0?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CED6BA295\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:43:44 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781f84-001a-006b-7375-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:43 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share112342ce0?restype=share&comp=snapshot", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "x-ms-snapshot" : "2019-07-23T16:43:44.0000000Z", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CED6BA295\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:43:44 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781f86-001a-006b-7475-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:44 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share112342ce1?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CED7C4768\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:43:45 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781f87-001a-006b-7575-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:44 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share112342ce2?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CED8745EA\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:43:45 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781f89-001a-006b-7675-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:44 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share112342ce2?restype=share&comp=snapshot", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "x-ms-snapshot" : "2019-07-23T16:43:45.0000000Z", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CED8745EA\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:43:45 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781f8b-001a-006b-7775-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:44 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net?prefix=share112342ce&include=metadata%2csnapshots&comp=list", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781f8c-001a-006b-7875-4192c4000000", + "Body" : "share112342ceshare112342ce02019-07-23T16:43:44.0000000ZTue, 23 Jul 2019 16:43:44 GMT\"0x8D70F8CED6BA295\"2metadatashare112342ce0Tue, 23 Jul 2019 16:43:44 GMT\"0x8D70F8CED6BA295\"2metadatashare112342ce1Tue, 23 Jul 2019 16:43:45 GMT\"0x8D70F8CED7C4768\"2share112342ce22019-07-23T16:43:45.0000000ZTue, 23 Jul 2019 16:43:45 GMT\"0x8D70F8CED8745EA\"2metadatashare112342ce2Tue, 23 Jul 2019 16:43:45 GMT\"0x8D70F8CED8745EA\"2metadata", + "Date" : "Tue, 23 Jul 2019 16:43:44 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net?prefix=share112342ce&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781f8d-001a-006b-7975-4192c4000000", + "Body" : "share112342ceshare112342ce0Tue, 23 Jul 2019 16:43:44 GMT\"0x8D70F8CED6BA295\"2share112342ce1Tue, 23 Jul 2019 16:43:45 GMT\"0x8D70F8CED7C4768\"2share112342ce2Tue, 23 Jul 2019 16:43:45 GMT\"0x8D70F8CED8745EA\"2", + "Date" : "Tue, 23 Jul 2019 16:43:44 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share112342ce0?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareHasSnapshots", + "retry-after" : "0", + "Content-Length" : "250", + "StatusCode" : "409", + "x-ms-request-id" : "a4781f8e-001a-006b-7a75-4192c4000000", + "Body" : "ShareHasSnapshotsThe share has snapshots and the operation requires no snapshots.\nRequestId:a4781f8e-001a-006b-7a75-4192c4000000\nTime:2019-07-23T16:43:45.3519776Z", + "Date" : "Tue, 23 Jul 2019 16:43:44 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share112342ce1?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781f8f-001a-006b-7b75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:44 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share112342ce2?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareHasSnapshots", + "retry-after" : "0", + "Content-Length" : "250", + "StatusCode" : "409", + "x-ms-request-id" : "a4781f90-001a-006b-7c75-4192c4000000", + "Body" : "ShareHasSnapshotsThe share has snapshots and the operation requires no snapshots.\nRequestId:a4781f90-001a-006b-7c75-4192c4000000\nTime:2019-07-23T16:43:45.4540500Z", + "Date" : "Tue, 23 Jul 2019 16:43:44 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "share112342ce" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/listSharesIncludeSnapshots.json b/storage/client/file/src/test/resources/session-records/listSharesIncludeSnapshots.json new file mode 100644 index 0000000000000..9274ad655d14a --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/listSharesIncludeSnapshots.json @@ -0,0 +1,186 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share305309dc0?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CEE49A7FE\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:43:46 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781faa-001a-006b-0f75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:45 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share305309dc0?restype=share&comp=snapshot", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "x-ms-snapshot" : "2019-07-23T16:43:46.0000000Z", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CEE49A7FE\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:43:46 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781fac-001a-006b-1075-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:45 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share305309dc1?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CEE5A4CDF\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:43:46 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781fad-001a-006b-1175-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:45 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share305309dc2?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CEE6CC6C8\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:43:46 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781faf-001a-006b-1275-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:45 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share305309dc2?restype=share&comp=snapshot", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "x-ms-snapshot" : "2019-07-23T16:43:46.0000000Z", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CEE6CC6C8\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:43:46 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781fb1-001a-006b-1375-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:45 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net?prefix=share305309dc&include=snapshots&comp=list", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781fb2-001a-006b-1475-4192c4000000", + "Body" : "share305309dcshare305309dc02019-07-23T16:43:46.0000000ZTue, 23 Jul 2019 16:43:46 GMT\"0x8D70F8CEE49A7FE\"2share305309dc0Tue, 23 Jul 2019 16:43:46 GMT\"0x8D70F8CEE49A7FE\"2share305309dc1Tue, 23 Jul 2019 16:43:46 GMT\"0x8D70F8CEE5A4CDF\"2share305309dc22019-07-23T16:43:46.0000000ZTue, 23 Jul 2019 16:43:46 GMT\"0x8D70F8CEE6CC6C8\"2share305309dc2Tue, 23 Jul 2019 16:43:46 GMT\"0x8D70F8CEE6CC6C8\"2", + "Date" : "Tue, 23 Jul 2019 16:43:45 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net?prefix=share305309dc&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781fb3-001a-006b-1575-4192c4000000", + "Body" : "share305309dcshare305309dc0Tue, 23 Jul 2019 16:43:46 GMT\"0x8D70F8CEE49A7FE\"2share305309dc1Tue, 23 Jul 2019 16:43:46 GMT\"0x8D70F8CEE5A4CDF\"2share305309dc2Tue, 23 Jul 2019 16:43:46 GMT\"0x8D70F8CEE6CC6C8\"2", + "Date" : "Tue, 23 Jul 2019 16:43:45 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share305309dc0?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareHasSnapshots", + "retry-after" : "0", + "Content-Length" : "250", + "StatusCode" : "409", + "x-ms-request-id" : "a4781fb4-001a-006b-1675-4192c4000000", + "Body" : "ShareHasSnapshotsThe share has snapshots and the operation requires no snapshots.\nRequestId:a4781fb4-001a-006b-1675-4192c4000000\nTime:2019-07-23T16:43:46.8250278Z", + "Date" : "Tue, 23 Jul 2019 16:43:45 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share305309dc1?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781fb5-001a-006b-1775-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:45 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share305309dc2?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareHasSnapshots", + "retry-after" : "0", + "Content-Length" : "250", + "StatusCode" : "409", + "x-ms-request-id" : "a4781fb6-001a-006b-1875-4192c4000000", + "Body" : "ShareHasSnapshotsThe share has snapshots and the operation requires no snapshots.\nRequestId:a4781fb6-001a-006b-1875-4192c4000000\nTime:2019-07-23T16:43:46.9331058Z", + "Date" : "Tue, 23 Jul 2019 16:43:45 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "share305309dc" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/listSharesInvalidMaxResults.json b/storage/client/file/src/test/resources/session-records/listSharesInvalidMaxResults.json new file mode 100644 index 0000000000000..82d415fce89ee --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/listSharesInvalidMaxResults.json @@ -0,0 +1,60 @@ +{ + "networkCallRecords" : [ { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net?prefix=share557594ed&maxresults=-1&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "OutOfRangeQueryParameterValue", + "retry-after" : "0", + "Content-Length" : "461", + "StatusCode" : "400", + "x-ms-request-id" : "a4781fe0-001a-006b-3775-4192c4000000", + "Body" : "OutOfRangeQueryParameterValueOne of the query parameters specified in the request URI is outside the permissible range.\nRequestId:a4781fe0-001a-006b-3775-4192c4000000\nTime:2019-07-23T16:43:48.6823538Zmaxresults-112147483647", + "Date" : "Tue, 23 Jul 2019 16:43:47 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net?prefix=share557594ed&maxresults=0&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "OutOfRangeQueryParameterValue", + "retry-after" : "0", + "Content-Length" : "460", + "StatusCode" : "400", + "x-ms-request-id" : "a4781fe1-001a-006b-3875-4192c4000000", + "Body" : "OutOfRangeQueryParameterValueOne of the query parameters specified in the request URI is outside the permissible range.\nRequestId:a4781fe1-001a-006b-3875-4192c4000000\nTime:2019-07-23T16:43:48.7303877Zmaxresults012147483647", + "Date" : "Tue, 23 Jul 2019 16:43:47 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net?prefix=share557594ed&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781fe2-001a-006b-3975-4192c4000000", + "Body" : "share557594ed", + "Date" : "Tue, 23 Jul 2019 16:43:47 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "share557594ed" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/listSharesWithLimit.json b/storage/client/file/src/test/resources/session-records/listSharesWithLimit.json new file mode 100644 index 0000000000000..ba78ebd77bdae --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/listSharesWithLimit.json @@ -0,0 +1,142 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share058285ff0?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CECCDBF15\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:43:43 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781f6c-001a-006b-6075-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:42 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share058285ff1?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CECD62507\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:43:43 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781f6e-001a-006b-6175-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:42 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share058285ff2?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CECDDC795\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:43:44 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781f70-001a-006b-6275-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:43 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net?prefix=share058285ff&maxresults=2&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781f72-001a-006b-6375-4192c4000000", + "Body" : "share058285ff2share058285ff0Tue, 23 Jul 2019 16:43:43 GMT\"0x8D70F8CECCDBF15\"2share058285ff1Tue, 23 Jul 2019 16:43:43 GMT\"0x8D70F8CECD62507\"2/sima/share058285ff2", + "Date" : "Tue, 23 Jul 2019 16:43:43 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net?prefix=share058285ff&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781f73-001a-006b-6475-4192c4000000", + "Body" : "share058285ffshare058285ff0Tue, 23 Jul 2019 16:43:43 GMT\"0x8D70F8CECCDBF15\"2share058285ff1Tue, 23 Jul 2019 16:43:43 GMT\"0x8D70F8CECD62507\"2share058285ff2Tue, 23 Jul 2019 16:43:44 GMT\"0x8D70F8CECDDC795\"2", + "Date" : "Tue, 23 Jul 2019 16:43:43 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share058285ff0?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781f74-001a-006b-6575-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:43 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share058285ff1?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781f75-001a-006b-6675-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:43 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share058285ff2?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781f76-001a-006b-6775-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:43 GMT" + } + } ], + "variables" : [ "share058285ff" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/listSharesWithPrefix.json b/storage/client/file/src/test/resources/session-records/listSharesWithPrefix.json new file mode 100644 index 0000000000000..eec9f6affa44f --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/listSharesWithPrefix.json @@ -0,0 +1,142 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share98599009prefix0?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CEEA9B3D7\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:43:47 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781fb7-001a-006b-1975-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:46 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share985990091?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CEEB48B44\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:43:47 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781fb9-001a-006b-1a75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:46 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share98599009prefix2?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CEEBC7BF7\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:43:47 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781fbb-001a-006b-1b75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:46 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net?prefix=share98599009prefix&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781fbd-001a-006b-1c75-4192c4000000", + "Body" : "share98599009prefixshare98599009prefix0Tue, 23 Jul 2019 16:43:47 GMT\"0x8D70F8CEEA9B3D7\"2share98599009prefix2Tue, 23 Jul 2019 16:43:47 GMT\"0x8D70F8CEEBC7BF7\"2", + "Date" : "Tue, 23 Jul 2019 16:43:46 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net?prefix=share98599009&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781fbe-001a-006b-1d75-4192c4000000", + "Body" : "share98599009share985990091Tue, 23 Jul 2019 16:43:47 GMT\"0x8D70F8CEEB48B44\"2share98599009prefix0Tue, 23 Jul 2019 16:43:47 GMT\"0x8D70F8CEEA9B3D7\"2share98599009prefix2Tue, 23 Jul 2019 16:43:47 GMT\"0x8D70F8CEEBC7BF7\"2", + "Date" : "Tue, 23 Jul 2019 16:43:46 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share985990091?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781fbf-001a-006b-1e75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:46 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share98599009prefix0?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781fc0-001a-006b-1f75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:46 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share98599009prefix2?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781fc1-001a-006b-2075-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:46 GMT" + } + } ], + "variables" : [ "share98599009" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/setFileServiceProperties.json b/storage/client/file/src/test/resources/session-records/setFileServiceProperties.json new file mode 100644 index 0000000000000..c72087f424609 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/setFileServiceProperties.json @@ -0,0 +1,110 @@ +{ + "networkCallRecords" : [ { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net?restype=service&comp=properties", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781fcf-001a-006b-2b75-4192c4000000", + "Body" : "1.0truetruetrue71.0falsefalse", + "Date" : "Tue, 23 Jul 2019 16:43:47 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net?restype=service&comp=properties", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781fd0-001a-006b-2c75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:47 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net?restype=service&comp=properties", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781fd5-001a-006b-2d75-4192c4000000", + "Body" : "1.0truefalsetrue31.0truefalsetrue3", + "Date" : "Tue, 23 Jul 2019 16:43:47 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net?restype=service&comp=properties", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781fd6-001a-006b-2e75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:43:47 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net?restype=service&comp=properties", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781fd7-001a-006b-2f75-4192c4000000", + "Body" : "1.0truetruetrue71.0falsefalse", + "Date" : "Tue, 23 Jul 2019 16:43:47 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net?prefix=share6218730e&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781fd8-001a-006b-3075-4192c4000000", + "Body" : "share6218730e", + "Date" : "Tue, 23 Jul 2019 16:43:47 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "share6218730e" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/setHttpHeadersFromFileClient.json b/storage/client/file/src/test/resources/session-records/setHttpHeadersFromFileClient.json new file mode 100644 index 0000000000000..2c2ad20a05635 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/setHttpHeadersFromFileClient.json @@ -0,0 +1,42 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/filesharename/testdir%2ffile81885521", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C3EAD5747\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:38:51 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781c33-001a-006b-3875-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:38:51 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/filesharename/testdir%2ffile81885521?comp=properties", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C3EB5962E\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:38:51 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781c34-001a-006b-3975-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:38:51 GMT" + } + } ], + "variables" : [ "file81885521" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/setMeatadataFromFileClient.json b/storage/client/file/src/test/resources/session-records/setMeatadataFromFileClient.json new file mode 100644 index 0000000000000..636ea1308eec5 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/setMeatadataFromFileClient.json @@ -0,0 +1,42 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/filesharename/testdir%2ffile571383d4", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C3ECFB295\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:38:51 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781c37-001a-006b-3c75-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:38:51 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/filesharename/testdir%2ffile571383d4?comp=metadata", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C3ED81888\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:38:52 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781c38-001a-006b-3d75-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:38:51 GMT" + } + } ], + "variables" : [ "file571383d4" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/setMetadataDoesNotExistFromShareClient.json b/storage/client/file/src/test/resources/session-records/setMetadataDoesNotExistFromShareClient.json new file mode 100644 index 0000000000000..a5c5b574deedc --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/setMetadataDoesNotExistFromShareClient.json @@ -0,0 +1,42 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share7646218d?restype=share&comp=metadata", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "a4781dbb-001a-006b-7675-4192c4000000", + "Body" : "ShareNotFoundThe specified share does not exist.\nRequestId:a4781dbb-001a-006b-7675-4192c4000000\nTime:2019-07-23T16:41:16.3775365Z", + "Date" : "Tue, 23 Jul 2019 16:41:15 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share7646218d?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "a4781dbc-001a-006b-7775-4192c4000000", + "Body" : "ShareNotFoundThe specified share does not exist.\nRequestId:a4781dbc-001a-006b-7775-4192c4000000\nTime:2019-07-23T16:41:16.4265718Z", + "Date" : "Tue, 23 Jul 2019 16:41:15 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "share7646218d" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/setMetadataFromDirClient.json b/storage/client/file/src/test/resources/session-records/setMetadataFromDirClient.json new file mode 100644 index 0000000000000..6ecfa9d794603 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/setMetadataFromDirClient.json @@ -0,0 +1,42 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory54792b?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB5439FA6\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:10 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781ebc-001a-006b-1475-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:42:09 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory54792b?restype=directory&comp=metadata", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB54B9056\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:10 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781ebd-001a-006b-1575-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:42:09 GMT" + } + } ], + "variables" : [ "directory54792b" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/setMetadataFromShareClient.json b/storage/client/file/src/test/resources/session-records/setMetadataFromShareClient.json new file mode 100644 index 0000000000000..51d3bce22d346 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/setMetadataFromShareClient.json @@ -0,0 +1,78 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share75460f03?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C790176C5\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:29 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781d4d-001a-006b-4c75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:28 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share75460f03?restype=share&comp=metadata", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C79099325\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:29 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781d4f-001a-006b-4d75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:28 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net/share75460f03?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:29 GMT", + "retry-after" : "0", + "StatusCode" : "200", + "Date" : "Tue, 23 Jul 2019 16:40:29 GMT", + "x-ms-has-legal-hold" : "false", + "x-ms-share-quota" : "5120", + "ETag" : "\"0x8D70F8C79099325\"", + "x-ms-has-immutability-policy" : "false", + "x-ms-meta-setting" : "metadata", + "Content-Length" : "0", + "x-ms-request-id" : "a4781d50-001a-006b-4e75-4192c4000000" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share75460f03?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781d51-001a-006b-4f75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:29 GMT" + } + } ], + "variables" : [ "share75460f03" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/setMetadataInvalidKeyFromDirClient.json b/storage/client/file/src/test/resources/session-records/setMetadataInvalidKeyFromDirClient.json new file mode 100644 index 0000000000000..ca338623cd5ab --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/setMetadataInvalidKeyFromDirClient.json @@ -0,0 +1,42 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory04212f?restype=directory", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8CB53321EA\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:42:10 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781eba-001a-006b-1275-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:42:09 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/dirsharename/directory04212f?restype=directory&comp=metadata", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "InvalidMetadata", + "retry-after" : "0", + "Content-Length" : "260", + "StatusCode" : "400", + "x-ms-request-id" : "a4781ebb-001a-006b-1375-4192c4000000", + "Body" : "InvalidMetadataThe metadata specified is invalid. It has characters that are not permitted.\nRequestId:a4781ebb-001a-006b-1375-4192c4000000\nTime:2019-07-23T16:42:10.6604019Z", + "Date" : "Tue, 23 Jul 2019 16:42:09 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "directory04212f" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/setMetadataInvalidMetadataFromShareClient.json b/storage/client/file/src/test/resources/session-records/setMetadataInvalidMetadataFromShareClient.json new file mode 100644 index 0000000000000..993c6b5ed18c0 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/setMetadataInvalidMetadataFromShareClient.json @@ -0,0 +1,57 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share911321d2?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C95EA6042\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:41:18 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781dde-001a-006b-1175-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:41:17 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share911321d2?restype=share&comp=metadata", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "EmptyMetadataKey", + "retry-after" : "0", + "Content-Length" : "281", + "StatusCode" : "400", + "x-ms-request-id" : "a4781de1-001a-006b-1275-4192c4000000", + "Body" : "EmptyMetadataKeyThe key for one of the metadata key-value pairs is empty.\nRequestId:a4781de1-001a-006b-1275-4192c4000000\nTime:2019-07-23T16:41:18.1748228Zmetadata", + "Date" : "Tue, 23 Jul 2019 16:41:17 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share911321d2?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781de2-001a-006b-1375-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:41:17 GMT" + } + } ], + "variables" : [ "share911321d2" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/setPolicies.json b/storage/client/file/src/test/resources/session-records/setPolicies.json new file mode 100644 index 0000000000000..a5247ae91c9ee --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/setPolicies.json @@ -0,0 +1,77 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share62017f60?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C7703C30B\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:26 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781d05-001a-006b-1475-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:25 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share62017f60?restype=share&comp=acl", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C770BDF57\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:26 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781d07-001a-006b-1575-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:25 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net/share62017f60?restype=share&comp=acl", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C770BDF57\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:26 GMT", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781d08-001a-006b-1675-4192c4000000", + "Body" : "test2000-01-01T00:00:00.0000000Z2020-01-01T00:00:00.0000000Zr", + "Date" : "Tue, 23 Jul 2019 16:40:25 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share62017f60?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781d09-001a-006b-1775-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:25 GMT" + } + } ], + "variables" : [ "share62017f60" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/setPoliciesDoesNotExist.json b/storage/client/file/src/test/resources/session-records/setPoliciesDoesNotExist.json new file mode 100644 index 0000000000000..6f5ee4c9407d8 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/setPoliciesDoesNotExist.json @@ -0,0 +1,43 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share49743cbd?restype=share&comp=acl", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "a4781d43-001a-006b-4475-4192c4000000", + "Body" : "ShareNotFoundThe specified share does not exist.\nRequestId:a4781d43-001a-006b-4475-4192c4000000\nTime:2019-07-23T16:40:29.1508343Z", + "Date" : "Tue, 23 Jul 2019 16:40:28 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share49743cbd?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "a4781d44-001a-006b-4575-4192c4000000", + "Body" : "ShareNotFoundThe specified share does not exist.\nRequestId:a4781d44-001a-006b-4575-4192c4000000\nTime:2019-07-23T16:40:29.2008691Z", + "Date" : "Tue, 23 Jul 2019 16:40:28 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "share49743cbd" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/setPoliciesInvalidPermission.json b/storage/client/file/src/test/resources/session-records/setPoliciesInvalidPermission.json new file mode 100644 index 0000000000000..f8c215e0dc597 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/setPoliciesInvalidPermission.json @@ -0,0 +1,58 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share2144443e?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C949D09C9\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:41:15 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781db0-001a-006b-6e75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:41:15 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share2144443e?restype=share&comp=acl", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "InvalidXmlDocument", + "retry-after" : "0", + "Content-Length" : "294", + "StatusCode" : "400", + "x-ms-request-id" : "a4781db2-001a-006b-6f75-4192c4000000", + "Body" : "InvalidXmlDocumentXML specified is not syntactically valid.\nRequestId:a4781db2-001a-006b-6f75-4192c4000000\nTime:2019-07-23T16:41:15.9892600Z00", + "Date" : "Tue, 23 Jul 2019 16:41:15 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share2144443e?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781db3-001a-006b-7075-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:41:15 GMT" + } + } ], + "variables" : [ "share2144443e" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/setPoliciesTooManyPermissions.json b/storage/client/file/src/test/resources/session-records/setPoliciesTooManyPermissions.json new file mode 100644 index 0000000000000..1e66291217bae --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/setPoliciesTooManyPermissions.json @@ -0,0 +1,58 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share28227ac8?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C77EA7C99\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:27 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781d26-001a-006b-2e75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:27 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share28227ac8?restype=share&comp=acl", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "InvalidXmlDocument", + "retry-after" : "0", + "Content-Length" : "294", + "StatusCode" : "400", + "x-ms-request-id" : "a4781d29-001a-006b-3075-4192c4000000", + "Body" : "InvalidXmlDocumentXML specified is not syntactically valid.\nRequestId:a4781d29-001a-006b-3075-4192c4000000\nTime:2019-07-23T16:40:27.8429018Z00", + "Date" : "Tue, 23 Jul 2019 16:40:27 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share28227ac8?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781d2b-001a-006b-3275-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:27 GMT" + } + } ], + "variables" : [ "share28227ac8" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/setPropertiesDoesNotExistFromShareClient.json b/storage/client/file/src/test/resources/session-records/setPropertiesDoesNotExistFromShareClient.json new file mode 100644 index 0000000000000..61be09fe38782 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/setPropertiesDoesNotExistFromShareClient.json @@ -0,0 +1,42 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share74233b07?restype=share&comp=properties", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "a4781dd6-001a-006b-0a75-4192c4000000", + "Body" : "ShareNotFoundThe specified share does not exist.\nRequestId:a4781dd6-001a-006b-0a75-4192c4000000\nTime:2019-07-23T16:41:17.7485158Z", + "Date" : "Tue, 23 Jul 2019 16:41:16 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share74233b07?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "a4781dd7-001a-006b-0b75-4192c4000000", + "Body" : "ShareNotFoundThe specified share does not exist.\nRequestId:a4781dd7-001a-006b-0b75-4192c4000000\nTime:2019-07-23T16:41:17.7975514Z", + "Date" : "Tue, 23 Jul 2019 16:41:17 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "share74233b07" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/setPropertiesFromShareClient.json b/storage/client/file/src/test/resources/session-records/setPropertiesFromShareClient.json new file mode 100644 index 0000000000000..e137e0a5800e6 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/setPropertiesFromShareClient.json @@ -0,0 +1,98 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share71347507?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C95C1E93A\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:41:17 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781dd8-001a-006b-0c75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:41:17 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net/share71347507?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "x-ms-share-quota" : "2", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C95C1E93A\"", + "x-ms-has-immutability-policy" : "false", + "Last-Modified" : "Tue, 23 Jul 2019 16:41:17 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781dda-001a-006b-0d75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:41:17 GMT", + "x-ms-has-legal-hold" : "false" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share71347507?restype=share&comp=properties", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C95D17F11\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:41:17 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781ddb-001a-006b-0e75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:41:17 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net/share71347507?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "x-ms-share-quota" : "4", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C95D17F11\"", + "x-ms-has-immutability-policy" : "false", + "Last-Modified" : "Tue, 23 Jul 2019 16:41:17 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781ddc-001a-006b-0f75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:41:17 GMT", + "x-ms-has-legal-hold" : "false" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share71347507?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781ddd-001a-006b-1075-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:41:17 GMT" + } + } ], + "variables" : [ "share71347507" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/setPropertiesInvalidAllowedHeader.json b/storage/client/file/src/test/resources/session-records/setPropertiesInvalidAllowedHeader.json new file mode 100644 index 0000000000000..64f1db166613b --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/setPropertiesInvalidAllowedHeader.json @@ -0,0 +1,42 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net?restype=service&comp=properties", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "InvalidXmlDocument", + "retry-after" : "0", + "Content-Length" : "294", + "StatusCode" : "400", + "x-ms-request-id" : "a4781fc2-001a-006b-2175-4192c4000000", + "Body" : "InvalidXmlDocumentXML specified is not syntactically valid.\nRequestId:a4781fc2-001a-006b-2175-4192c4000000\nTime:2019-07-23T16:43:47.4734913Z00", + "Date" : "Tue, 23 Jul 2019 16:43:46 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net?prefix=share42833eb8&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781fc3-001a-006b-2275-4192c4000000", + "Body" : "share42833eb8", + "Date" : "Tue, 23 Jul 2019 16:43:46 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "share42833eb8" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/setPropertiesInvalidAllowedMethod.json b/storage/client/file/src/test/resources/session-records/setPropertiesInvalidAllowedMethod.json new file mode 100644 index 0000000000000..bde0f4c241c81 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/setPropertiesInvalidAllowedMethod.json @@ -0,0 +1,42 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net?restype=service&comp=properties", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "InvalidXmlNodeValue", + "retry-after" : "0", + "Content-Length" : "340", + "StatusCode" : "400", + "x-ms-request-id" : "a4781fd9-001a-006b-3175-4192c4000000", + "Body" : "InvalidXmlNodeValueThe value for one of the XML nodes is not in the correct format.\nRequestId:a4781fd9-001a-006b-3175-4192c4000000\nTime:2019-07-23T16:43:48.3661282ZAllowedMethodsNOTAREALHTTPMETHOD", + "Date" : "Tue, 23 Jul 2019 16:43:47 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net?prefix=share26492564&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781fda-001a-006b-3275-4192c4000000", + "Body" : "share26492564", + "Date" : "Tue, 23 Jul 2019 16:43:47 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "share26492564" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/setPropertiesInvalidAllowedOrigin.json b/storage/client/file/src/test/resources/session-records/setPropertiesInvalidAllowedOrigin.json new file mode 100644 index 0000000000000..fa758d47e3eff --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/setPropertiesInvalidAllowedOrigin.json @@ -0,0 +1,42 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net?restype=service&comp=properties", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "InvalidXmlDocument", + "retry-after" : "0", + "Content-Length" : "294", + "StatusCode" : "400", + "x-ms-request-id" : "a4781fdc-001a-006b-3375-4192c4000000", + "Body" : "InvalidXmlDocumentXML specified is not syntactically valid.\nRequestId:a4781fdc-001a-006b-3375-4192c4000000\nTime:2019-07-23T16:43:48.4682010Z00", + "Date" : "Tue, 23 Jul 2019 16:43:47 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net?prefix=share46216ea8&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781fdd-001a-006b-3475-4192c4000000", + "Body" : "share46216ea8", + "Date" : "Tue, 23 Jul 2019 16:43:47 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "share46216ea8" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/setPropertiesInvalidExposedHeader.json b/storage/client/file/src/test/resources/session-records/setPropertiesInvalidExposedHeader.json new file mode 100644 index 0000000000000..9020928319556 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/setPropertiesInvalidExposedHeader.json @@ -0,0 +1,42 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net?restype=service&comp=properties", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "InvalidXmlDocument", + "retry-after" : "0", + "Content-Length" : "294", + "StatusCode" : "400", + "x-ms-request-id" : "a4781fde-001a-006b-3575-4192c4000000", + "Body" : "InvalidXmlDocumentXML specified is not syntactically valid.\nRequestId:a4781fde-001a-006b-3575-4192c4000000\nTime:2019-07-23T16:43:48.5772777Z00", + "Date" : "Tue, 23 Jul 2019 16:43:47 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net?prefix=share66999f9c&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781fdf-001a-006b-3675-4192c4000000", + "Body" : "share66999f9c", + "Date" : "Tue, 23 Jul 2019 16:43:47 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "share66999f9c" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/setPropertiesInvalidQuotaFromShareClient.json b/storage/client/file/src/test/resources/session-records/setPropertiesInvalidQuotaFromShareClient.json new file mode 100644 index 0000000000000..768a60b78cadd --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/setPropertiesInvalidQuotaFromShareClient.json @@ -0,0 +1,76 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share46729b2d?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C788159EC\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:28 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781d3a-001a-006b-3d75-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:28 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share46729b2d?restype=share&comp=properties", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "InvalidHeaderValue", + "retry-after" : "0", + "Content-Length" : "324", + "StatusCode" : "400", + "x-ms-request-id" : "a4781d3c-001a-006b-3e75-4192c4000000", + "Body" : "InvalidHeaderValueThe value for one of the HTTP headers is not in the correct format.\nRequestId:a4781d3c-001a-006b-3e75-4192c4000000\nTime:2019-07-23T16:40:28.8296045Zx-ms-share-quota-1", + "Date" : "Tue, 23 Jul 2019 16:40:28 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share46729b2d?restype=share&comp=properties", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "InvalidHeaderValue", + "retry-after" : "0", + "Content-Length" : "326", + "StatusCode" : "400", + "x-ms-request-id" : "a4781d3d-001a-006b-3f75-4192c4000000", + "Body" : "InvalidHeaderValueThe value for one of the HTTP headers is not in the correct format.\nRequestId:a4781d3d-001a-006b-3f75-4192c4000000\nTime:2019-07-23T16:40:28.8756373Zx-ms-share-quota9999", + "Date" : "Tue, 23 Jul 2019 16:40:28 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share46729b2d?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a4781d3e-001a-006b-4075-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:28 GMT" + } + } ], + "variables" : [ "share46729b2d" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/setPropertiesTooManyRules.json b/storage/client/file/src/test/resources/session-records/setPropertiesTooManyRules.json new file mode 100644 index 0000000000000..885ff107c99ed --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/setPropertiesTooManyRules.json @@ -0,0 +1,42 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net?restype=service&comp=properties", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "InvalidXmlDocument", + "retry-after" : "0", + "Content-Length" : "294", + "StatusCode" : "400", + "x-ms-request-id" : "a4781f7e-001a-006b-6e75-4192c4000000", + "Body" : "InvalidXmlDocumentXML specified is not syntactically valid.\nRequestId:a4781f7e-001a-006b-6e75-4192c4000000\nTime:2019-07-23T16:43:44.6374670Z00", + "Date" : "Tue, 23 Jul 2019 16:43:43 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net?prefix=share41569da0&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "a4781f7f-001a-006b-6f75-4192c4000000", + "Body" : "share41569da0", + "Date" : "Tue, 23 Jul 2019 16:43:43 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "share41569da0" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/snapshot.json b/storage/client/file/src/test/resources/session-records/snapshot.json new file mode 100644 index 0000000000000..08e6b88615e55 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/snapshot.json @@ -0,0 +1,60 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share14716ca7?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C793BF261\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:30 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781d55-001a-006b-5275-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:29 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share14716ca7?restype=share&comp=snapshot", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "x-ms-snapshot" : "2019-07-23T16:40:30.0000000Z", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C793BF261\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:30 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781d57-001a-006b-5375-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:29 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share14716ca7?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareHasSnapshots", + "retry-after" : "0", + "Content-Length" : "250", + "StatusCode" : "409", + "x-ms-request-id" : "a4781d58-001a-006b-5475-4192c4000000", + "Body" : "ShareHasSnapshotsThe share has snapshots and the operation requires no snapshots.\nRequestId:a4781d58-001a-006b-5475-4192c4000000\nTime:2019-07-23T16:40:30.1135230Z", + "Date" : "Tue, 23 Jul 2019 16:40:29 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "share14716ca7" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/snapshotDifferentMetadata.json b/storage/client/file/src/test/resources/session-records/snapshotDifferentMetadata.json new file mode 100644 index 0000000000000..ff7dd6c695507 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/snapshotDifferentMetadata.json @@ -0,0 +1,104 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share10771b10?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C777A1A17\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:27 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781d17-001a-006b-2275-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:26 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share10771b10?restype=share&comp=snapshot", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "x-ms-snapshot" : "2019-07-23T16:40:27.0000000Z", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C7771CF80\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:27 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781d19-001a-006b-2375-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:40:26 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net/share10771b10?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:27 GMT", + "retry-after" : "0", + "StatusCode" : "200", + "Date" : "Tue, 23 Jul 2019 16:40:26 GMT", + "x-ms-has-legal-hold" : "false", + "x-ms-meta-create" : "metadata", + "x-ms-share-quota" : "2", + "ETag" : "\"0x8D70F8C777A1A17\"", + "x-ms-has-immutability-policy" : "false", + "Content-Length" : "0", + "x-ms-request-id" : "a4781d1a-001a-006b-2475-4192c4000000" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net/share10771b10?sharesnapshot=2019-07-23T16%3a40%3a27.0000000Z&restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-meta-update" : "metadata", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "Last-Modified" : "Tue, 23 Jul 2019 16:40:27 GMT", + "retry-after" : "0", + "StatusCode" : "200", + "Date" : "Tue, 23 Jul 2019 16:40:26 GMT", + "x-ms-has-legal-hold" : "false", + "x-ms-share-quota" : "2", + "ETag" : "\"0x8D70F8C7771CF80\"", + "x-ms-has-immutability-policy" : "false", + "Content-Length" : "0", + "x-ms-request-id" : "3975b150-b01a-003d-1775-417ab4000000" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share10771b10?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareHasSnapshots", + "retry-after" : "0", + "Content-Length" : "250", + "StatusCode" : "409", + "x-ms-request-id" : "a4781d1b-001a-006b-2575-4192c4000000", + "Body" : "ShareHasSnapshotsThe share has snapshots and the operation requires no snapshots.\nRequestId:a4781d1b-001a-006b-2575-4192c4000000\nTime:2019-07-23T16:40:27.2825020Z", + "Date" : "Tue, 23 Jul 2019 16:40:26 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "share10771b10" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/snapshotDoesNotExist.json b/storage/client/file/src/test/resources/session-records/snapshotDoesNotExist.json new file mode 100644 index 0000000000000..364519a28f53c --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/snapshotDoesNotExist.json @@ -0,0 +1,42 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share00244732?restype=share&comp=snapshot", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "a4781d45-001a-006b-4675-4192c4000000", + "Body" : "ShareNotFoundThe specified share does not exist.\nRequestId:a4781d45-001a-006b-4675-4192c4000000\nTime:2019-07-23T16:40:29.2589105Z", + "Date" : "Tue, 23 Jul 2019 16:40:28 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share00244732?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "a4781d47-001a-006b-4775-4192c4000000", + "Body" : "ShareNotFoundThe specified share does not exist.\nRequestId:a4781d47-001a-006b-4775-4192c4000000\nTime:2019-07-23T16:40:29.3079458Z", + "Date" : "Tue, 23 Jul 2019 16:40:28 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "share00244732" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/snapshotSameMetadata.json b/storage/client/file/src/test/resources/session-records/snapshotSameMetadata.json new file mode 100644 index 0000000000000..0e5c5452621c0 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/snapshotSameMetadata.json @@ -0,0 +1,82 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share60407a93?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C958F1003\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:41:17 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781dd2-001a-006b-0775-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:41:16 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/share60407a93?restype=share&comp=snapshot", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "x-ms-snapshot" : "2019-07-23T16:41:17.0000000Z", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C953F3480\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:41:17 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781dd4-001a-006b-0875-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:41:16 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net/share60407a93?sharesnapshot=2019-07-23T16%3a41%3a17.0000000Z&restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-meta-test" : "metadata", + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "Last-Modified" : "Tue, 23 Jul 2019 16:41:17 GMT", + "retry-after" : "0", + "StatusCode" : "200", + "Date" : "Tue, 23 Jul 2019 16:41:16 GMT", + "x-ms-has-legal-hold" : "false", + "x-ms-share-quota" : "2", + "ETag" : "\"0x8D70F8C953F3480\"", + "x-ms-has-immutability-policy" : "false", + "Content-Length" : "0", + "x-ms-request-id" : "3975b191-b01a-003d-2775-417ab4000000" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.file.core.windows.net/share60407a93?restype=share", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "ShareHasSnapshots", + "retry-after" : "0", + "Content-Length" : "250", + "StatusCode" : "409", + "x-ms-request-id" : "a4781dd5-001a-006b-0975-4192c4000000", + "Body" : "ShareHasSnapshotsThe share has snapshots and the operation requires no snapshots.\nRequestId:a4781dd5-001a-006b-0975-4192c4000000\nTime:2019-07-23T16:41:17.6894731Z", + "Date" : "Tue, 23 Jul 2019 16:41:16 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "share60407a93" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/startCopy.json b/storage/client/file/src/test/resources/session-records/startCopy.json new file mode 100644 index 0000000000000..f2a527cd8e4b9 --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/startCopy.json @@ -0,0 +1,43 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/filesharename/testdir%2ffile8920181a", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C3DB97C52\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:38:50 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781c20-001a-006b-2775-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:38:49 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/filesharename/testdir%2ffile8920181a", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-copy-id" : "2d272a59-d40b-4b67-8fc2-b66d8aa4a210", + "ETag" : "\"0x8D70F8C3DDF5ACE\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:38:50 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "x-ms-copy-status" : "success", + "StatusCode" : "202", + "x-ms-request-id" : "a4781c21-001a-006b-2875-4192c4000000", + "Date" : "Tue, 23 Jul 2019 16:38:49 GMT" + } + } ], + "variables" : [ "file8920181a" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/upload.json b/storage/client/file/src/test/resources/session-records/upload.json new file mode 100644 index 0000000000000..457a29b5542cf --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/upload.json @@ -0,0 +1,44 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/filesharename/testdir%2ffile98350d88", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C3E2EC19B\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:38:50 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781c2b-001a-006b-3075-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:38:50 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/filesharename/testdir%2ffile98350d88?comp=range", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/octet-stream" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C3E372789\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:38:50 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781c2c-001a-006b-3175-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:38:50 GMT", + "Content-MD5" : "wh+Wm18D0z1D4E+PE252gg==" + } + } ], + "variables" : [ "file98350d88" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/uploadToStorageAndDownloadToFile.json b/storage/client/file/src/test/resources/session-records/uploadToStorageAndDownloadToFile.json new file mode 100644 index 0000000000000..dbc17e4548a1f --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/uploadToStorageAndDownloadToFile.json @@ -0,0 +1,90 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/filesharename/testdir%2ffile11163511", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C3E4050F6\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:38:51 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781c2d-001a-006b-3275-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:38:50 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.file.core.windows.net/filesharename/testdir%2ffile11163511?comp=range", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/octet-stream" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "\"0x8D70F8C3E4ED28D\"", + "Last-Modified" : "Tue, 23 Jul 2019 16:38:51 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "a4781c2e-001a-006b-3375-4192c4000000", + "x-ms-request-server-encrypted" : "true", + "Date" : "Tue, 23 Jul 2019 16:38:50 GMT", + "Content-MD5" : "/CTzx8jXJ1MqqUsC1dJBUQ==" + } + }, { + "Method" : "HEAD", + "Uri" : "https://sima.file.core.windows.net/filesharename/testdir%2ffile11163511", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "Last-Modified" : "Tue, 23 Jul 2019 16:38:51 GMT", + "retry-after" : "0", + "StatusCode" : "200", + "Date" : "Tue, 23 Jul 2019 16:38:50 GMT", + "x-ms-server-encrypted" : "true", + "x-ms-type" : "File", + "ETag" : "\"0x8D70F8C3E4ED28D\"", + "Content-Length" : "14", + "x-ms-request-id" : "a4781c2f-001a-006b-3475-4192c4000000", + "Body" : "", + "Content-Type" : "application/octet-stream" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.file.core.windows.net/filesharename/testdir%2ffile11163511", + "Headers" : { + "x-ms-version" : "2018-11-09", + "User-Agent" : "azsdk-java-azure-storage-file/12.0.0-preview.1 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-11-09", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "Content-Range" : "bytes 0-13/14", + "Last-Modified" : "Tue, 23 Jul 2019 16:38:51 GMT", + "retry-after" : "0", + "StatusCode" : "206", + "Date" : "Tue, 23 Jul 2019 16:38:51 GMT", + "Accept-Ranges" : "bytes", + "x-ms-server-encrypted" : "true", + "x-ms-type" : "File", + "ETag" : "\"0x8D70F8C3E4ED28D\"", + "Content-Length" : "14", + "x-ms-request-id" : "a4781c30-001a-006b-3575-4192c4000000", + "Body" : "Hello world!\r\n", + "Content-Type" : "application/octet-stream" + } + } ], + "variables" : [ "file11163511" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/session-records/urlFromDirClient.json b/storage/client/file/src/test/resources/session-records/urlFromDirClient.json new file mode 100644 index 0000000000000..11fc90ded8aec --- /dev/null +++ b/storage/client/file/src/test/resources/session-records/urlFromDirClient.json @@ -0,0 +1,4 @@ +{ + "networkCallRecords" : [ ], + "variables" : [ "directory100251" ] +} \ No newline at end of file diff --git a/storage/client/file/src/test/resources/testfiles/helloworld b/storage/client/file/src/test/resources/testfiles/helloworld new file mode 100644 index 0000000000000..cd0875583aabe --- /dev/null +++ b/storage/client/file/src/test/resources/testfiles/helloworld @@ -0,0 +1 @@ +Hello world! diff --git a/storage/client/pom.xml b/storage/client/pom.xml new file mode 100644 index 0000000000000..645574936759e --- /dev/null +++ b/storage/client/pom.xml @@ -0,0 +1,123 @@ + + + 4.0.0 + + com.azure + azure-client-sdk-parent + 1.0.0 + ../../pom.client.xml + + + com.azure + azure-storage + 12.0.0 + + Microsoft Azure client library for Storage + This package contains the Microsoft Azure Storage client library. + https://github.com/Azure/azure-sdk-for-java + + + + azure-java-build-docs + ${site.url}/site/${project.artifactId} + + + + + scm:git:https://github.com/Azure/azure-sdk-for-java + scm:git:git@github.com:Azure/azure-sdk-for-java.git + HEAD + + + + + com.azure + azure-core + 1.0.0-preview.1 + + + + + + + org.slf4j + slf4j-api + + + + com.azure + azure-core-test + 1.0.0-preview.1 + test + + + junit + junit + test + + + org.slf4j + slf4j-simple + test + + + io.projectreactor + reactor-test + test + + + com.microsoft.azure + adal4j + test + + + org.spockframework + spock-core + test + + + cglib + cglib-nodep + test + + + uk.org.lidalia + slf4j-test + test + + + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + false + false + + + + org.apache.maven.plugins + maven-javadoc-plugin + + false + false + + + + + com.github.spotbugs + spotbugs-maven-plugin + + false + + + + + diff --git a/storage/client/queue/README.md b/storage/client/queue/README.md index 436f7e6f2094a..18f92018e21c5 100644 --- a/storage/client/queue/README.md +++ b/storage/client/queue/README.md @@ -369,10 +369,10 @@ When you interact with queue using this Java client library, errors returned by ### More Samples Get started with our [Queue samples][samples]: -- [QueueServiceSample](src/samples/java/blob/QueueServiceSample.java): Create, list and delete queues -- [MessageSample](src/samples/java/blob/MessageSample.java): Enqueue, peek dequeue, update, clear and delete messages. Get properties of the queue. -- [QueueExceptionSample](src/samples/java/blob/QueueExceptionSample.java): Handle the exceptions from storage queue service side. -- [AsyncSample](src/samples/java/blob/AsyncSample.java): Create queue and enqueue message using async queue client call. +- [QueueServiceSample](src/samples/java/queue/QueueServiceSample.java): Create, list and delete queues +- [MessageSample](src/samples/java/queue/MessageSample.java): Enqueue, peek dequeue, update, clear and delete messages. Get properties of the queue. +- [QueueExceptionSample](src/samples/java/queue/QueueExceptionSample.java): Handle the exceptions from storage queue service side. +- [AsyncSample](src/samples/java/queue/AsyncSample.java): Create queue and enqueue message using async queue client call. [Quickstart: Create a Java Spring app with App Configuration](https://docs.microsoft.com/en-us/azure/azure-app-configuration/quickstart-java-spring-app)