From 1ec9438d210a125ec9b265c121a9b70c217e5922 Mon Sep 17 00:00:00 2001 From: Gauri Prasad <51212198+gapra-msft@users.noreply.github.com> Date: Fri, 12 Jul 2019 11:57:48 -0700 Subject: [PATCH 01/17] Storage SAS implementation (#4404) * SAS implementation * Fixed some minor formatting issues * Fixed checkstyle problems and test issue --- .../azure/storage/blob/BlobAsyncClient.java | 259 ++++ .../com/azure/storage/blob/BlobClient.java | 207 ++++ .../com/azure/storage/blob/Constants.java | 15 + .../storage/blob/ContainerAsyncClient.java | 231 ++++ .../azure/storage/blob/ContainerClient.java | 188 +++ .../storage/blob/SASQueryParameters.java | 4 +- .../blob/ServiceSASSignatureValues.java | 182 +-- .../storage/blob/StorageAsyncClient.java | 70 ++ .../com/azure/storage/blob/StorageClient.java | 49 + .../java/com/azure/storage/blob/Utility.java | 23 + .../credentials/SASTokenCredential.java | 96 +- .../policy/SharedKeyCredentialPolicy.java | 9 + .../com/azure/storage/blob/SASTest.groovy | 1079 +++++++++++++++++ 13 files changed, 2315 insertions(+), 97 deletions(-) create mode 100644 storage/client/blob/src/test/java/com/azure/storage/blob/SASTest.groovy diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobAsyncClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobAsyncClient.java index 7ec72ecf30b53..5042f9e782af5 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobAsyncClient.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobAsyncClient.java @@ -21,6 +21,8 @@ import com.azure.storage.blob.models.ModifiedAccessConditions; import com.azure.storage.blob.models.ReliableDownloadOptions; import com.azure.storage.blob.models.StorageAccountInfo; +import com.azure.storage.blob.models.UserDelegationKey; +import com.azure.storage.common.credentials.SharedKeyCredential; import io.netty.buffer.ByteBuf; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -35,6 +37,7 @@ import java.nio.channels.AsynchronousFileChannel; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; +import java.time.OffsetDateTime; import java.util.ArrayList; import java.util.List; @@ -774,4 +777,260 @@ public Mono> getAccountInfo() { .getAccountInfo() .map(rb -> new SimpleResponse<>(rb, new StorageAccountInfo(rb.deserializedHeaders()))); } + + /** + * Generates a user delegation SAS with the specified parameters + * + * @param userDelegationKey + * The {@code UserDelegationKey} user delegation key for the SAS + * @param accountName + * The {@code String} account name for the SAS + * @param permissions + * The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime + * The {@code OffsetDateTime} expiry time for the SAS + * + * @return + * A string that represents the SAS token + */ + public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, String accountName, + BlobSASPermission permissions, OffsetDateTime expiryTime) { + return this.generateUserDelegationSAS(userDelegationKey, accountName, permissions, expiryTime, null /* + startTime */, null /* version */, null /*sasProtocol */, null /* ipRange */, null /* cacheControl */, null + /*contentDisposition */, null /* contentEncoding */, null /* contentLanguage */, null /* contentType */); + } + + /** + * Generates a user delegation SAS token with the specified parameters + * + * @param userDelegationKey + * The {@code UserDelegationKey} user delegation key for the SAS + * @param accountName + * The {@code String} account name for the SAS + * @param permissions + * The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime + * The {@code OffsetDateTime} expiry time for the SAS + * @param startTime + * An optional {@code OffsetDateTime} start time for the SAS + * @param version + * An optional {@code String} version for the SAS + * @param sasProtocol + * An optional {@code SASProtocol} protocol for the SAS + * @param ipRange + * An optional {@code IPRange} ip address range for the SAS + * + * @return + * A string that represents the SAS token + */ + public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, String accountName, + BlobSASPermission permissions, OffsetDateTime expiryTime, OffsetDateTime startTime, String version, + SASProtocol sasProtocol, IPRange ipRange) { + return this.generateUserDelegationSAS(userDelegationKey, accountName, permissions, expiryTime, startTime, + version, sasProtocol, ipRange, null /* cacheControl */, null /* contentDisposition */, null /* + contentEncoding */, null /* contentLanguage */, null /* contentType */); + } + + /** + * Generates a user delegation SAS token with the specified parameters + * + * @param userDelegationKey + * The {@code UserDelegationKey} user delegation key for the SAS + * @param accountName + * The {@code String} account name for the SAS + * @param permissions + * The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime + * The {@code OffsetDateTime} expiry time for the SAS + * @param startTime + * An optional {@code OffsetDateTime} start time for the SAS + * @param version + * An optional {@code String} version for the SAS + * @param sasProtocol + * An optional {@code SASProtocol} protocol for the SAS + * @param ipRange + * An optional {@code IPRange} ip address range for the SAS + * @param cacheControl + * An optional {@code String} cache-control header for the SAS. + * @param contentDisposition + * An optional {@code String} content-disposition header for the SAS. + * @param contentEncoding + * An optional {@code String} content-encoding header for the SAS. + * @param contentLanguage + * An optional {@code String} content-language header for the SAS. + * @param contentType + * An optional {@code String} content-type header for the SAS. + * + * @return + * A string that represents the SAS token + */ + public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, String accountName, + BlobSASPermission permissions, OffsetDateTime expiryTime, OffsetDateTime startTime, String version, + SASProtocol sasProtocol, IPRange ipRange, String cacheControl, String contentDisposition, + String contentEncoding, String contentLanguage, String contentType) { + + ServiceSASSignatureValues serviceSASSignatureValues = new ServiceSASSignatureValues(version, sasProtocol, + startTime, expiryTime, permissions == null ? null : permissions.toString(), ipRange, null /* identifier*/, + cacheControl, contentDisposition, contentEncoding, contentLanguage, contentType); + + ServiceSASSignatureValues values = configureServiceSASSignatureValues(serviceSASSignatureValues, accountName); + + SASQueryParameters sasQueryParameters = values.generateSASQueryParameters(userDelegationKey); + + return sasQueryParameters.encode(); + } + + /** + * Generates a SAS token with the specified parameters + * + * @param permissions + * The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime + * The {@code OffsetDateTime} expiry time for the SAS + * + * @return + * A string that represents the SAS token + */ + public String generateSAS(BlobSASPermission permissions, OffsetDateTime expiryTime) { + return this.generateSAS(null, permissions, expiryTime, null /* startTime */, /* identifier */ null /* + version */, null /* sasProtocol */, null /* ipRange */, null /* cacheControl */, null /* contentLanguage*/, + null /* contentEncoding */, null /* contentLanguage */, null /* contentType */); + } + + /** + * Generates a SAS token with the specified parameters + * + * @param identifier + * The {@code String} name of the access policy on the container this SAS references if any + * + * @return + * A string that represents the SAS token + */ + public String generateSAS(String identifier) { + return this.generateSAS(identifier, null /* permissions */, null /* expiryTime */, null /* startTime */, + null /* version */, null /* sasProtocol */, null /* ipRange */, null /* cacheControl */, null /* + contentLanguage*/, null /* contentEncoding */, null /* contentLanguage */, null /* contentType */); + } + + /** + * Generates a SAS token with the specified parameters + * + * @param identifier + * The {@code String} name of the access policy on the container this SAS references if any + * @param permissions + * The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime + * The {@code OffsetDateTime} expiry time for the SAS + * @param startTime + * An optional {@code OffsetDateTime} start time for the SAS + * @param version + * An optional {@code String} version for the SAS + * @param sasProtocol + * An optional {@code SASProtocol} protocol for the SAS + * @param ipRange + * An optional {@code IPRange} ip address range for the SAS + * + * @return + * A string that represents the SAS token + */ + public String generateSAS(String identifier, BlobSASPermission permissions, OffsetDateTime expiryTime, + OffsetDateTime startTime, String version, SASProtocol sasProtocol, IPRange ipRange) { + return this.generateSAS(identifier, permissions, expiryTime, startTime, version, sasProtocol, ipRange, null + /* cacheControl */, null /* contentLanguage*/, null /* contentEncoding */, null /* contentLanguage */, + null /* contentType */); + } + + /** + * Generates a SAS token with the specified parameters + * + * @param identifier + * The {@code String} name of the access policy on the container this SAS references if any + * @param permissions + * The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime + * The {@code OffsetDateTime} expiry time for the SAS + * @param startTime + * An optional {@code OffsetDateTime} start time for the SAS + * @param version + * An optional {@code String} version for the SAS + * @param sasProtocol + * An optional {@code SASProtocol} protocol for the SAS + * @param ipRange + * An optional {@code IPRange} ip address range for the SAS + * @param cacheControl + * An optional {@code String} cache-control header for the SAS. + * @param contentDisposition + * An optional {@code String} content-disposition header for the SAS. + * @param contentEncoding + * An optional {@code String} content-encoding header for the SAS. + * @param contentLanguage + * An optional {@code String} content-language header for the SAS. + * @param contentType + * An optional {@code String} content-type header for the SAS. + * + * @return + * A string that represents the SAS token + */ + public String generateSAS(String identifier, BlobSASPermission permissions, OffsetDateTime expiryTime, + OffsetDateTime startTime, String version, SASProtocol sasProtocol, IPRange ipRange, String cacheControl, + String contentDisposition, String contentEncoding, String contentLanguage, String contentType) { + + ServiceSASSignatureValues serviceSASSignatureValues = new ServiceSASSignatureValues(version, sasProtocol, + startTime, expiryTime, permissions == null ? null : permissions.toString(), ipRange, identifier, + cacheControl, contentDisposition, contentEncoding, contentLanguage, contentType); + + SharedKeyCredential sharedKeyCredential = + Utility.getSharedKeyCredential(this.blobAsyncRawClient.azureBlobStorage.httpPipeline()); + + Utility.assertNotNull("sharedKeyCredential", sharedKeyCredential); + + ServiceSASSignatureValues values = configureServiceSASSignatureValues(serviceSASSignatureValues, + sharedKeyCredential.accountName()); + + SASQueryParameters sasQueryParameters = values.generateSASQueryParameters(sharedKeyCredential); + + return sasQueryParameters.encode(); + } + + /** + * Sets serviceSASSignatureValues parameters dependent on the current blob type + */ + ServiceSASSignatureValues configureServiceSASSignatureValues(ServiceSASSignatureValues serviceSASSignatureValues, + String accountName) { + + // Set canonical name + serviceSASSignatureValues.canonicalName(this.blobAsyncRawClient.azureBlobStorage.url(), accountName); + + // Set snapshotId + serviceSASSignatureValues.snapshotId(getSnapshotId()); + + // Set resource + if (isSnapshot()) { + serviceSASSignatureValues.resource(Constants.UrlConstants.SAS_BLOB_SNAPSHOT_CONSTANT); + } else { + serviceSASSignatureValues.resource(Constants.UrlConstants.SAS_BLOB_CONSTANT); + } + + return serviceSASSignatureValues; + } + + /** + * Gets the snapshotId for a blob resource + * + * @return + * A string that represents the snapshotId of the snapshot blob + */ + public String getSnapshotId() { + return this.blobAsyncRawClient.snapshot; + } + + /** + * Determines if a blob is a snapshot + * + * @return + * A boolean that indicates if a blob is a snapshot + */ + public boolean isSnapshot() { + return this.blobAsyncRawClient.snapshot != null; + } } diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobClient.java index f47c3cf6d7830..21a2212713f5c 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobClient.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobClient.java @@ -16,6 +16,7 @@ import com.azure.storage.blob.models.ModifiedAccessConditions; import com.azure.storage.blob.models.ReliableDownloadOptions; import com.azure.storage.blob.models.StorageAccountInfo; +import com.azure.storage.blob.models.UserDelegationKey; import reactor.core.publisher.Mono; import java.io.IOException; @@ -23,6 +24,7 @@ import java.io.UncheckedIOException; import java.net.URL; import java.time.Duration; +import java.time.OffsetDateTime; /** * Client to a blob of any type: block, append, or page. It may only be instantiated through a {@link BlobClientBuilder} or via @@ -800,4 +802,209 @@ public Response getAccountInfo(Duration timeout) { return Utility.blockWithOptionalTimeout(response, timeout); } + + /** + * Generates a user delegation SAS token with the specified parameters + * + * @param userDelegationKey + * The {@code UserDelegationKey} user delegation key for the SAS + * @param accountName + * The {@code String} account name for the SAS + * @param permissions + * The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime + * The {@code OffsetDateTime} expiry time for the SAS + * + * @return + * A string that represents the SAS token + */ + public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, String accountName, + BlobSASPermission permissions, OffsetDateTime expiryTime) { + return this.blobAsyncClient.generateUserDelegationSAS(userDelegationKey, accountName, permissions, expiryTime); + } + + /** + * Generates a user delegation SAS token with the specified parameters + * + * @param userDelegationKey + * The {@code UserDelegationKey} user delegation key for the SAS + * @param accountName + * The {@code String} account name for the SAS + * @param permissions + * The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime + * The {@code OffsetDateTime} expiry time for the SAS + * @param startTime + * An optional {@code OffsetDateTime} start time for the SAS + * @param version + * An optional {@code String} version for the SAS + * @param sasProtocol + * An optional {@code SASProtocol} protocol for the SAS + * @param ipRange + * An optional {@code IPRange} ip address range for the SAS + * + * @return + * A string that represents the SAS token + */ + public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, String accountName, + BlobSASPermission permissions, OffsetDateTime expiryTime, OffsetDateTime startTime, String version, + SASProtocol sasProtocol, IPRange ipRange) { + return this.blobAsyncClient.generateUserDelegationSAS(userDelegationKey, accountName, permissions, expiryTime, + startTime, version, sasProtocol, ipRange); + } + + /** + * Generates a user delegation SAS token with the specified parameters + * + * @param userDelegationKey + * The {@code UserDelegationKey} user delegation key for the SAS + * @param accountName + * The {@code String} account name for the SAS + * @param permissions + * The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime + * The {@code OffsetDateTime} expiry time for the SAS + * @param startTime + * An optional {@code OffsetDateTime} start time for the SAS + * @param version + * An optional {@code String} version for the SAS + * @param sasProtocol + * An optional {@code SASProtocol} protocol for the SAS + * @param ipRange + * An optional {@code IPRange} ip address range for the SAS + * @param cacheControl + * An optional {@code String} cache-control header for the SAS. + * @param contentDisposition + * An optional {@code String} content-disposition header for the SAS. + * @param contentEncoding + * An optional {@code String} content-encoding header for the SAS. + * @param contentLanguage + * An optional {@code String} content-language header for the SAS. + * @param contentType + * An optional {@code String} content-type header for the SAS. + * + * @return + * A string that represents the SAS token + */ + public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, String accountName, + BlobSASPermission permissions, OffsetDateTime expiryTime, OffsetDateTime startTime, String version, + SASProtocol sasProtocol, IPRange ipRange, String cacheControl, String contentDisposition, + String contentEncoding, String contentLanguage, String contentType) { + return this.blobAsyncClient.generateUserDelegationSAS(userDelegationKey, accountName, permissions, expiryTime, + startTime, version, sasProtocol, ipRange, cacheControl, contentDisposition, contentEncoding, + contentLanguage, contentType); + } + + /** + * Generates a SAS token with the specified parameters + * + * @param expiryTime + * The {@code OffsetDateTime} expiry time for the SAS + * @param permissions + * The {@code ContainerSASPermissions} permission for the SAS + * + * @return + * A string that represents the SAS token + */ + public String generateSAS(OffsetDateTime expiryTime, BlobSASPermission permissions) { + return this.blobAsyncClient.generateSAS(permissions, expiryTime); + } + + /** + * Generates a SAS token with the specified parameters + * + * @param identifier + * The {@code String} name of the access policy on the container this SAS references if any + * + * @return + * A string that represents the SAS token + */ + public String generateSAS(String identifier) { + return this.blobAsyncClient.generateSAS(identifier); + } + + /** + * Generates a SAS token with the specified parameters + * + * @param identifier + * The {@code String} name of the access policy on the container this SAS references if any + * @param permissions + * The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime + * The {@code OffsetDateTime} expiry time for the SAS + * @param startTime + * An optional {@code OffsetDateTime} start time for the SAS + * @param version + * An optional {@code String} version for the SAS + * @param sasProtocol + * An optional {@code SASProtocol} protocol for the SAS + * @param ipRange + * An optional {@code IPRange} ip address range for the SAS + * + * @return + * A string that represents the SAS token + */ + public String generateSAS(String identifier, BlobSASPermission permissions, OffsetDateTime expiryTime, + OffsetDateTime startTime, String version, SASProtocol sasProtocol, IPRange ipRange) { + return this.blobAsyncClient.generateSAS(identifier, permissions, expiryTime, startTime, version, sasProtocol, + ipRange); + } + + /** + * Generates a SAS token with the specified parameters + * + * @param identifier + * The {@code String} name of the access policy on the container this SAS references if any + * @param permissions + * The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime + * The {@code OffsetDateTime} expiry time for the SAS + * @param startTime + * An optional {@code OffsetDateTime} start time for the SAS + * @param version + * An optional {@code String} version for the SAS + * @param sasProtocol + * An optional {@code SASProtocol} protocol for the SAS + * @param ipRange + * An optional {@code IPRange} ip address range for the SAS + * @param cacheControl + * An optional {@code String} cache-control header for the SAS. + * @param contentDisposition + * An optional {@code String} content-disposition header for the SAS. + * @param contentEncoding + * An optional {@code String} content-encoding header for the SAS. + * @param contentLanguage + * An optional {@code String} content-language header for the SAS. + * @param contentType + * An optional {@code String} content-type header for the SAS. + * + * @return + * A string that represents the SAS token + */ + public String generateSAS(String identifier, BlobSASPermission permissions, OffsetDateTime expiryTime, + OffsetDateTime startTime, String version, SASProtocol sasProtocol, IPRange ipRange, String cacheControl, + String contentDisposition, String contentEncoding, String contentLanguage, String contentType) { + return this.blobAsyncClient.generateSAS(identifier, permissions, expiryTime, startTime, version, sasProtocol, + ipRange, cacheControl, contentDisposition, contentEncoding, contentLanguage, contentType); + } + + /** + * Gets the snapshotId for a blob resource + * + * @return + * A string that represents the snapshotId of the snapshot blob + */ + public String getSnapshotId() { + return this.blobAsyncClient.getSnapshotId(); + } + + /** + * Determines if a blob is a snapshot + * + * @return + * A boolean that indicates if a blob is a snapshot + */ + public boolean isSnapshot() { + return this.blobAsyncClient.isSnapshot(); + } } diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/Constants.java b/storage/client/blob/src/main/java/com/azure/storage/blob/Constants.java index 653625b572c15..fa812df4b531b 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/Constants.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/Constants.java @@ -288,6 +288,21 @@ static final class UrlConstants { */ public static final String SAS_SIGNED_KEY_VERSION = "skv"; + /** + * The SAS blob constant. + */ + public static final String SAS_BLOB_CONSTANT = "b"; + + /** + * The SAS blob snapshot constant. + */ + public static final String SAS_BLOB_SNAPSHOT_CONSTANT = "bs"; + + /** + * The SAS blob snapshot constant. + */ + public static final String SAS_CONTAINER_CONSTANT = "c"; + private UrlConstants() { // Private to prevent construction. } diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerAsyncClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerAsyncClient.java index 406a7440b0c5b..f979f084ac151 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerAsyncClient.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerAsyncClient.java @@ -24,12 +24,15 @@ import com.azure.storage.blob.models.PublicAccessType; import com.azure.storage.blob.models.SignedIdentifier; import com.azure.storage.blob.models.StorageAccountInfo; +import com.azure.storage.blob.models.UserDelegationKey; +import com.azure.storage.common.credentials.SharedKeyCredential; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.net.MalformedURLException; import java.net.URL; import java.time.Duration; +import java.time.OffsetDateTime; import java.util.List; /** @@ -878,4 +881,232 @@ public Mono> getAccountInfo() { .getAccountInfo() .map(rb -> new SimpleResponse<>(rb, new StorageAccountInfo(rb.deserializedHeaders()))); } + + /** + * Generates a user delegation SAS with the specified parameters + * + * @param userDelegationKey + * The {@code UserDelegationKey} user delegation key for the SAS + * @param accountName + * The {@code String} account name for the SAS + * @param permissions + * The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime + * The {@code OffsetDateTime} expiry time for the SAS + * + * @return + * A string that represents the SAS token + */ + public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, String accountName, + ContainerSASPermission permissions, OffsetDateTime expiryTime) { + return this.generateUserDelegationSAS(userDelegationKey, accountName, permissions, expiryTime, null /* + startTime */, null /* version */, null /* sasProtocol */, null /* ipRange */, null /* cacheControl */, null + /* contentDisposition */, null /* contentEncoding */, null /* contentLanguage */, null /* contentType */); + } + + /** + * Generates a user delegation SAS token with the specified parameters + * + * @param userDelegationKey + * The {@code UserDelegationKey} user delegation key for the SAS + * @param accountName + * The {@code String} account name for the SAS + * @param permissions + * The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime + * The {@code OffsetDateTime} expiry time for the SAS + * @param startTime + * An optional {@code OffsetDateTime} start time for the SAS + * @param version + * An optional {@code String} version for the SAS + * @param sasProtocol + * An optional {@code SASProtocol} protocol for the SAS + * @param ipRange + * An optional {@code IPRange} ip address range for the SAS + * + * @return + * A string that represents the SAS token + */ + public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, String accountName, + ContainerSASPermission permissions, OffsetDateTime expiryTime, OffsetDateTime startTime, String version, + SASProtocol sasProtocol, IPRange ipRange) { + return this.generateUserDelegationSAS(userDelegationKey, accountName, permissions, expiryTime, startTime, + version, sasProtocol, ipRange, null /* cacheControl */, null /* contentDisposition */, null /* + contentEncoding */, null /* contentLanguage */, null /* contentType */); + } + + /** + * Generates a user delegation SAS token with the specified parameters + * + * @param userDelegationKey + * The {@code UserDelegationKey} user delegation key for the SAS + * @param accountName + * The {@code String} account name for the SAS + * @param permissions + * The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime + * The {@code OffsetDateTime} expiry time for the SAS + * @param startTime + * An optional {@code OffsetDateTime} start time for the SAS + * @param version + * An optional {@code String} version for the SAS + * @param sasProtocol + * An optional {@code SASProtocol} protocol for the SAS + * @param ipRange + * An optional {@code IPRange} ip address range for the SAS + * @param cacheControl + * An optional {@code String} cache-control header for the SAS. + * @param contentDisposition + * An optional {@code String} content-disposition header for the SAS. + * @param contentEncoding + * An optional {@code String} content-encoding header for the SAS. + * @param contentLanguage + * An optional {@code String} content-language header for the SAS. + * @param contentType + * An optional {@code String} content-type header for the SAS. + * + * @return + * A string that represents the SAS token + */ + public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, String accountName, + ContainerSASPermission permissions, OffsetDateTime expiryTime, OffsetDateTime startTime, String version, + SASProtocol sasProtocol, IPRange ipRange, String cacheControl, String contentDisposition, + String contentEncoding, String contentLanguage, String contentType) { + ServiceSASSignatureValues serviceSASSignatureValues = new ServiceSASSignatureValues(version, sasProtocol, + startTime, expiryTime, permissions == null ? null : permissions.toString(), ipRange, null /* identifier*/, + cacheControl, contentDisposition, contentEncoding, contentLanguage, contentType); + + ServiceSASSignatureValues values = configureServiceSASSignatureValues(serviceSASSignatureValues, accountName); + + SASQueryParameters sasQueryParameters = values.generateSASQueryParameters(userDelegationKey); + + return sasQueryParameters.encode(); + } + + /** + * Generates a SAS token with the specified parameters + * + * @param permissions + * The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime + * The {@code OffsetDateTime} expiry time for the SAS + * + * @return + * A string that represents the SAS token + */ + public String generateSAS(ContainerSASPermission permissions, OffsetDateTime expiryTime) { + return this.generateSAS(null, permissions, /* identifier */ expiryTime, null /* startTime */, null /* version + */, null /* sasProtocol */, null /* ipRange */, null /* cacheControl */, null /* contentDisposition */, + null /* contentEncoding */, null /* contentLanguage */, null /*contentType*/); + } + + /** + * Generates a SAS token with the specified parameters + * + * @param identifier + * The {@code String} name of the access policy on the container this SAS references if any + * + * @return + * A string that represents the SAS token + */ + public String generateSAS(String identifier) { + return this.generateSAS(identifier, null /* permissions*/, null /* expiryTime */, null /* startTime */, null + /* version */, null /* sasProtocol */, null /* ipRange */, null /* cacheControl */, null /* + contentDisposition */, null /* contentEncoding */, null /* contentLanguage */, null /*contentType*/); + } + + /** + * Generates a SAS token with the specified parameters + * + * @param identifier + * The {@code String} name of the access policy on the container this SAS references if any + * @param permissions + * The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime + * The {@code OffsetDateTime} expiry time for the SAS + * @param startTime + * An optional {@code OffsetDateTime} start time for the SAS + * @param version + * An optional {@code String} version for the SAS + * @param sasProtocol + * An optional {@code SASProtocol} protocol for the SAS + * @param ipRange + * An optional {@code IPRange} ip address range for the SAS + * + * @return + * A string that represents the SAS token + */ + public String generateSAS(String identifier, ContainerSASPermission permissions, OffsetDateTime expiryTime, + OffsetDateTime startTime, + String version, SASProtocol sasProtocol, IPRange ipRange) { + return this.generateSAS(identifier, permissions, expiryTime, startTime, version, sasProtocol, ipRange, null + /* cacheControl */, null /* contentDisposition */, null /* contentEncoding */, null /* contentLanguage */, + null /*contentType*/); + } + + /** + * Generates a SAS token with the specified parameters + * + * @param identifier + * The {@code String} name of the access policy on the container this SAS references if any + * @param permissions + * The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime + * The {@code OffsetDateTime} expiry time for the SAS + * @param startTime + * An optional {@code OffsetDateTime} start time for the SAS + * @param version + * An optional {@code String} version for the SAS + * @param sasProtocol + * An optional {@code SASProtocol} protocol for the SAS + * @param ipRange + * An optional {@code IPRange} ip address range for the SAS + * @param cacheControl + * An optional {@code String} cache-control header for the SAS. + * @param contentDisposition + * An optional {@code String} content-disposition header for the SAS. + * @param contentEncoding + * An optional {@code String} content-encoding header for the SAS. + * @param contentLanguage + * An optional {@code String} content-language header for the SAS. + * @param contentType + * An optional {@code String} content-type header for the SAS. + * + * @return + * A string that represents the SAS token + */ + public String generateSAS(String identifier, ContainerSASPermission permissions, OffsetDateTime expiryTime, + OffsetDateTime startTime, String version, SASProtocol sasProtocol, IPRange ipRange, String cacheControl, + String contentDisposition, String contentEncoding, String contentLanguage, String contentType) { + ServiceSASSignatureValues serviceSASSignatureValues = new ServiceSASSignatureValues(version, sasProtocol, + startTime, expiryTime, permissions == null ? null : permissions.toString(), ipRange, identifier, + cacheControl, contentDisposition, contentEncoding, contentLanguage, contentType); + + SharedKeyCredential sharedKeyCredential = + Utility.getSharedKeyCredential(this.containerAsyncRawClient.azureBlobStorage.httpPipeline()); + + Utility.assertNotNull("sharedKeyCredential", sharedKeyCredential); + + ServiceSASSignatureValues values = configureServiceSASSignatureValues(serviceSASSignatureValues, + sharedKeyCredential.accountName()); + + SASQueryParameters sasQueryParameters = values.generateSASQueryParameters(sharedKeyCredential); + + return sasQueryParameters.encode(); + } + + /** + * Sets serviceSASSignatureValues parameters dependent on the current blob type + */ + private ServiceSASSignatureValues configureServiceSASSignatureValues(ServiceSASSignatureValues serviceSASSignatureValues, String accountName) { + // Set canonical name + serviceSASSignatureValues.canonicalName(this.containerAsyncRawClient.azureBlobStorage.url(), accountName); + + // Set snapshotId to null + serviceSASSignatureValues.snapshotId(null); + + // Set resource + serviceSASSignatureValues.resource(Constants.UrlConstants.SAS_CONTAINER_CONSTANT); + return serviceSASSignatureValues; + } } diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerClient.java index b8c1f9d8bd09e..c9733fd3a7f61 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerClient.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerClient.java @@ -15,11 +15,13 @@ import com.azure.storage.blob.models.PublicAccessType; import com.azure.storage.blob.models.SignedIdentifier; import com.azure.storage.blob.models.StorageAccountInfo; +import com.azure.storage.blob.models.UserDelegationKey; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.net.URL; import java.time.Duration; +import java.time.OffsetDateTime; import java.util.List; /** @@ -738,4 +740,190 @@ public Response getAccountInfo(Duration timeout) { return Utility.blockWithOptionalTimeout(response, timeout); } + + /** + * Generates a user delegation SAS token with the specified parameters + * + * @param userDelegationKey + * The {@code UserDelegationKey} user delegation key for the SAS + * @param accountName + * The {@code String} account name for the SAS + * @param permissions + * The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime + * The {@code OffsetDateTime} expiry time for the SAS + * + * @return + * A string that represents the SAS token + */ + public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, String accountName, + ContainerSASPermission permissions, OffsetDateTime expiryTime) { + return this.containerAsyncClient.generateUserDelegationSAS(userDelegationKey, accountName, permissions, + expiryTime); + } + + /** + * Generates a user delegation SAS token with the specified parameters + * + * @param userDelegationKey + * The {@code UserDelegationKey} user delegation key for the SAS + * @param accountName + * The {@code String} account name for the SAS + * @param permissions + * The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime + * The {@code OffsetDateTime} expiry time for the SAS + * @param startTime + * An optional {@code OffsetDateTime} start time for the SAS + * @param version + * An optional {@code String} version for the SAS + * @param sasProtocol + * An optional {@code SASProtocol} protocol for the SAS + * @param ipRange + * An optional {@code IPRange} ip address range for the SAS + * + * @return + * A string that represents the SAS token + */ + public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, String accountName, + ContainerSASPermission permissions, OffsetDateTime expiryTime, OffsetDateTime startTime, String version, + SASProtocol sasProtocol, IPRange ipRange) { + return this.containerAsyncClient.generateUserDelegationSAS(userDelegationKey, accountName, permissions, + expiryTime, startTime, version, sasProtocol, ipRange); + } + + /** + * Generates a user delegation SAS token with the specified parameters + * + * @param userDelegationKey + * The {@code UserDelegationKey} user delegation key for the SAS + * @param accountName + * The {@code String} account name for the SAS + * @param permissions + * The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime + * The {@code OffsetDateTime} expiry time for the SAS + * @param startTime + * An optional {@code OffsetDateTime} start time for the SAS + * @param version + * An optional {@code String} version for the SAS + * @param sasProtocol + * An optional {@code SASProtocol} protocol for the SAS + * @param ipRange + * An optional {@code IPRange} ip address range for the SAS + * @param cacheControl + * An optional {@code String} cache-control header for the SAS. + * @param contentDisposition + * An optional {@code String} content-disposition header for the SAS. + * @param contentEncoding + * An optional {@code String} content-encoding header for the SAS. + * @param contentLanguage + * An optional {@code String} content-language header for the SAS. + * @param contentType + * An optional {@code String} content-type header for the SAS. + * + * @return + * A string that represents the SAS token + */ + public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, String accountName, + ContainerSASPermission permissions, OffsetDateTime expiryTime, OffsetDateTime startTime, String version, + SASProtocol sasProtocol, IPRange ipRange, String cacheControl, String contentDisposition, + String contentEncoding, String contentLanguage, String contentType) { + return this.containerAsyncClient.generateUserDelegationSAS(userDelegationKey, accountName, permissions, + expiryTime, startTime, version, sasProtocol, ipRange, cacheControl, contentDisposition, contentEncoding, + contentLanguage, contentType); + } + + /** + * Generates a SAS token with the specified parameters + * + * @param permissions + * The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime + * The {@code OffsetDateTime} expiry time for the SAS + * + * @return + * A string that represents the SAS token + */ + public String generateSAS(ContainerSASPermission permissions, OffsetDateTime expiryTime) { + return this.containerAsyncClient.generateSAS(permissions, expiryTime); + } + + /** + * Generates a SAS token with the specified parameters + * + * @param identifier + * The {@code String} name of the access policy on the container this SAS references if any + * + * @return + * A string that represents the SAS token + */ + public String generateSAS(String identifier) { + return this.containerAsyncClient.generateSAS(identifier); + } + + /** + * Generates a SAS token with the specified parameters + * + * @param identifier + * The {@code String} name of the access policy on the container this SAS references if any + * @param permissions + * The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime + * The {@code OffsetDateTime} expiry time for the SAS + * @param startTime + * An optional {@code OffsetDateTime} start time for the SAS + * @param version + * An optional {@code String} version for the SAS + * @param sasProtocol + * An optional {@code SASProtocol} protocol for the SAS + * @param ipRange + * An optional {@code IPRange} ip address range for the SAS + * + * @return + * A string that represents the SAS token + */ + public String generateSAS(String identifier, ContainerSASPermission permissions, OffsetDateTime expiryTime, + OffsetDateTime startTime, String version, SASProtocol sasProtocol, IPRange ipRange) { + return this.containerAsyncClient.generateSAS(identifier, permissions, expiryTime, startTime, version, + sasProtocol, ipRange); + } + + /** + * Generates a SAS token with the specified parameters + * + * @param identifier + * The {@code String} name of the access policy on the container this SAS references if any + * @param permissions + * The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime + * The {@code OffsetDateTime} expiry time for the SAS + * @param startTime + * An optional {@code OffsetDateTime} start time for the SAS + * @param version + * An optional {@code String} version for the SAS + * @param sasProtocol + * An optional {@code SASProtocol} protocol for the SAS + * @param ipRange + * An optional {@code IPRange} ip address range for the SAS + * @param cacheControl + * An optional {@code String} cache-control header for the SAS. + * @param contentDisposition + * An optional {@code String} content-disposition header for the SAS. + * @param contentEncoding + * An optional {@code String} content-encoding header for the SAS. + * @param contentLanguage + * An optional {@code String} content-language header for the SAS. + * @param contentType + * An optional {@code String} content-type header for the SAS. + * + * @return + * A string that represents the SAS token + */ + public String generateSAS(String identifier, ContainerSASPermission permissions, OffsetDateTime expiryTime, + OffsetDateTime startTime, String version, SASProtocol sasProtocol, IPRange ipRange, String cacheControl, + String contentDisposition, String contentEncoding, String contentLanguage, String contentType) { + return this.containerAsyncClient.generateSAS(identifier, permissions, expiryTime, startTime, version, + sasProtocol, ipRange, cacheControl, contentDisposition, contentEncoding, contentLanguage, contentType); + } } diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/SASQueryParameters.java b/storage/client/blob/src/main/java/com/azure/storage/blob/SASQueryParameters.java index b6afd82addcab..cd918e636bbd4 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/SASQueryParameters.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/SASQueryParameters.java @@ -333,9 +333,7 @@ UserDelegationKey userDelegationKey() { private void tryAppendQueryParameter(StringBuilder sb, String param, Object value) { if (value != null) { - if (sb.length() == 0) { - sb.append('?'); - } else { + if (sb.length() != 0) { sb.append('&'); } sb.append(safeURLEncode(param)).append('=').append(safeURLEncode(value.toString())); diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/ServiceSASSignatureValues.java b/storage/client/blob/src/main/java/com/azure/storage/blob/ServiceSASSignatureValues.java index 7450ae699f5a4..114c28eb71209 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/ServiceSASSignatureValues.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/ServiceSASSignatureValues.java @@ -6,6 +6,8 @@ import com.azure.storage.blob.models.UserDelegationKey; import com.azure.storage.common.credentials.SharedKeyCredential; +import java.net.MalformedURLException; +import java.net.URL; import java.security.InvalidKeyException; import java.time.OffsetDateTime; @@ -40,9 +42,9 @@ final class ServiceSASSignatureValues { private IPRange ipRange; - private String containerName; + private String canonicalName; - private String blobName; + private String resource; private String snapshotId; @@ -64,6 +66,43 @@ final class ServiceSASSignatureValues { ServiceSASSignatureValues() { } + /** + * Creates an object with the specified expiry time and permissions + * @param expiryTime + * @param permissions + */ + ServiceSASSignatureValues(OffsetDateTime expiryTime, String permissions) { + this.expiryTime = expiryTime; + this.permissions = permissions; + } + + /** + * Creates an object with the specified identifier + * @param identifier + */ + ServiceSASSignatureValues(String identifier) { + this.identifier = identifier; + } + + ServiceSASSignatureValues(String version, SASProtocol sasProtocol, OffsetDateTime startTime, + OffsetDateTime expiryTime, String permission, IPRange ipRange, String identifier, String cacheControl, + String contentDisposition, String contentEncoding, String contentLanguage, String contentType) { + if (version != null) { + this.version = version; + } + this.protocol = sasProtocol; + this.startTime = startTime; + this.expiryTime = expiryTime; + this.permissions = permission; + this.ipRange = ipRange; + this.identifier = identifier; + this.cacheControl = cacheControl; + this.contentDisposition = contentDisposition; + this.contentEncoding = contentEncoding; + this.contentLanguage = contentLanguage; + this.contentType = contentType; + } + /** * The version of the service this SAS will target. If not specified, it will default to the version targeted by the * library. @@ -159,32 +198,51 @@ public ServiceSASSignatureValues ipRange(IPRange ipRange) { } /** - * The name of the container the SAS user may access. + * The resource the SAS user may access. */ - public String containerName() { - return containerName; + public String resource() { + return resource; } /** - * The name of the container the SAS user may access. + * The resource the SAS user may access. */ - public ServiceSASSignatureValues containerName(String containerName) { - this.containerName = containerName; + public ServiceSASSignatureValues resource(String resource) { + this.resource = resource; return this; } /** - * The name of the blob the SAS user may access. + * The canonical name of the object the SAS user may access. */ - public String blobName() { - return blobName; + public String canonicalName() { + return canonicalName; } /** - * The name of the blob the SAS user may access. + * The canonical name of the object the SAS user may access. */ - public ServiceSASSignatureValues blobName(String blobName) { - this.blobName = blobName; + public ServiceSASSignatureValues canonicalName(String canonicalName) { + this.canonicalName = canonicalName; + return this; + } + + /** + * The canonical name of the object the SAS user may access. + * @throws RuntimeException If urlString is a malformed URL. + */ + public ServiceSASSignatureValues canonicalName(String urlString, String accountName) { + URL url = null; + try { + url = new URL(urlString); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + + StringBuilder canonicalName = new StringBuilder("/blob"); + canonicalName.append('/').append(accountName).append(url.getPath()); + this.canonicalName = canonicalName.toString(); + return this; } @@ -192,7 +250,7 @@ public ServiceSASSignatureValues blobName(String blobName) { * The specific snapshot the SAS user may access. */ public String snapshotId() { - return snapshotId; + return this.snapshotId; } /** @@ -309,13 +367,10 @@ public ServiceSASSignatureValues contentType(String contentType) { */ public SASQueryParameters generateSASQueryParameters(SharedKeyCredential sharedKeyCredentials) { Utility.assertNotNull("sharedKeyCredentials", sharedKeyCredentials); - assertGenerateOK(); - - String resource = getResource(); - String verifiedPermissions = getVerifiedPermissions(); + assertGenerateOK(false); // Signature is generated on the un-url-encoded values. - final String stringToSign = stringToSign(verifiedPermissions, resource, sharedKeyCredentials); + final String stringToSign = stringToSign(); String signature = null; try { @@ -336,22 +391,15 @@ public SASQueryParameters generateSASQueryParameters(SharedKeyCredential sharedK * @param delegationKey * A {@link UserDelegationKey} object used to sign the SAS values. * - * @param accountName - * Name of the account holding the resource this SAS is authorizing. - * * @return {@link SASQueryParameters} * @throws Error If the accountKey is not a valid Base64-encoded string. */ - public SASQueryParameters generateSASQueryParameters(UserDelegationKey delegationKey, String accountName) { + public SASQueryParameters generateSASQueryParameters(UserDelegationKey delegationKey) { Utility.assertNotNull("delegationKey", delegationKey); - Utility.assertNotNull("accountName", accountName); - assertGenerateOK(); - - String resource = getResource(); - String verifiedPermissions = getVerifiedPermissions(); + assertGenerateOK(true); // Signature is generated on the un-url-encoded values. - final String stringToSign = stringToSign(verifiedPermissions, resource, delegationKey, accountName); + final String stringToSign = stringToSign(delegationKey); String signature = null; try { @@ -369,70 +417,39 @@ public SASQueryParameters generateSASQueryParameters(UserDelegationKey delegatio /** * Common assertions for generateSASQueryParameters overloads. */ - private void assertGenerateOK() { + private void assertGenerateOK(boolean usingUserDelegation) { Utility.assertNotNull("version", this.version); - Utility.assertNotNull("containerName", this.containerName); - if (blobName == null && snapshotId != null) { - throw new IllegalArgumentException("Cannot set a snapshotId without a blobName."); - } - } + Utility.assertNotNull("canonicalName", this.canonicalName); - /** - * Gets the resource string for SAS tokens based on object state. - */ - private String getResource() { - String resource = "c"; - if (!Utility.isNullOrEmpty(this.blobName)) { - resource = snapshotId != null && !snapshotId.isEmpty() ? "bs" : "b"; - } - - return resource; - } - - /** - * Gets the verified permissions string for SAS tokens based on object state. - */ - private String getVerifiedPermissions() { - String verifiedPermissions = null; - // Calling parse and toString guarantees the proper ordering and throws on invalid characters. - if (Utility.isNullOrEmpty(this.blobName)) { - if (this.permissions != null) { - verifiedPermissions = ContainerSASPermission.parse(this.permissions).toString(); + // Ensure either (expiryTime and permissions) or (identifier) is set + if (this.expiryTime == null || this.permissions == null) { + // Identifier is not required if user delegation is being used + if (!usingUserDelegation) { + Utility.assertNotNull("identifier", this.identifier); } } else { - if (this.permissions != null) { - verifiedPermissions = BlobSASPermission.parse(this.permissions).toString(); - } + Utility.assertNotNull("expiryTime", this.expiryTime); + Utility.assertNotNull("permissions", this.permissions); } - return verifiedPermissions; - } - - private String getCanonicalName(String accountName) { - // Container: "/blob/account/containername" - // Blob: "/blob/account/containername/blobname" - StringBuilder canonicalName = new StringBuilder("/blob"); - canonicalName.append('/').append(accountName).append('/').append(this.containerName); - - if (!Utility.isNullOrEmpty(this.blobName)) { - canonicalName.append("/").append(this.blobName); + if (this.resource != null && this.resource.equals(Constants.UrlConstants.SAS_CONTAINER_CONSTANT)) { + if (this.snapshotId != null) { + throw new IllegalArgumentException("Cannot set a snapshotId without resource being a blob."); + } } - - return canonicalName.toString(); } - private String stringToSign(final String verifiedPermissions, final String resource, - final SharedKeyCredential sharedKeyCredentials) { + private String stringToSign() { return String.join("\n", - verifiedPermissions == null ? "" : verifiedPermissions, + this.permissions == null ? "" : this.permissions, this.startTime == null ? "" : Utility.ISO_8601_UTC_DATE_FORMATTER.format(this.startTime), this.expiryTime == null ? "" : Utility.ISO_8601_UTC_DATE_FORMATTER.format(this.expiryTime), - getCanonicalName(sharedKeyCredentials.accountName()), + this.canonicalName == null ? "" : this.canonicalName, this.identifier == null ? "" : this.identifier, this.ipRange == null ? (new IPRange()).toString() : this.ipRange.toString(), this.protocol == null ? "" : protocol.toString(), this.version == null ? "" : this.version, - resource == null ? "" : resource, + this.resource == null ? "" : this.resource, this.snapshotId == null ? "" : this.snapshotId, this.cacheControl == null ? "" : this.cacheControl, this.contentDisposition == null ? "" : this.contentDisposition, @@ -442,13 +459,12 @@ private String stringToSign(final String verifiedPermissions, final String resou ); } - private String stringToSign(final String verifiedPermissions, final String resource, - final UserDelegationKey key, final String accountName) { + private String stringToSign(final UserDelegationKey key) { return String.join("\n", - verifiedPermissions == null ? "" : verifiedPermissions, + this.permissions == null ? "" : this.permissions, this.startTime == null ? "" : Utility.ISO_8601_UTC_DATE_FORMATTER.format(this.startTime), this.expiryTime == null ? "" : Utility.ISO_8601_UTC_DATE_FORMATTER.format(this.expiryTime), - getCanonicalName(accountName), + this.canonicalName == null ? "" : this.canonicalName, key.signedOid() == null ? "" : key.signedOid(), key.signedTid() == null ? "" : key.signedTid(), key.signedStart() == null ? "" : Utility.ISO_8601_UTC_DATE_FORMATTER.format(key.signedStart()), @@ -458,7 +474,7 @@ private String stringToSign(final String verifiedPermissions, final String resou this.ipRange == null ? new IPRange().toString() : this.ipRange.toString(), this.protocol == null ? "" : this.protocol.toString(), this.version == null ? "" : this.version, - resource == null ? "" : resource, + this.resource == null ? "" : this.resource, this.snapshotId == null ? "" : this.snapshotId, this.cacheControl == null ? "" : this.cacheControl, this.contentDisposition == null ? "" : this.contentDisposition, diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/StorageAsyncClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/StorageAsyncClient.java index d5b0aecc3a3f1..c6c48d7e5770d 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/StorageAsyncClient.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/StorageAsyncClient.java @@ -18,6 +18,7 @@ import com.azure.storage.blob.models.StorageServiceProperties; import com.azure.storage.blob.models.StorageServiceStats; import com.azure.storage.blob.models.UserDelegationKey; +import com.azure.storage.common.credentials.SharedKeyCredential; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -233,4 +234,73 @@ public Mono> getAccountInfo() { .getAccountInfo() .map(rb -> new SimpleResponse<>(rb, new StorageAccountInfo(rb.deserializedHeaders()))); } + + /** + * Generates an account SAS token with the specified parameters + * + * @param accountSASService + * The {@code AccountSASService} services for the account SAS + * @param accountSASResourceType + * An optional {@code AccountSASResourceType} resources for the account SAS + * @param accountSASPermission + * The {@code AccountSASPermission} permission for the account SAS + * @param expiryTime + * The {@code OffsetDateTime} expiry time for the account SAS + * + * @return + * A string that represents the SAS token + */ + public String generateAccountSAS(AccountSASService accountSASService, AccountSASResourceType accountSASResourceType, + AccountSASPermission accountSASPermission, OffsetDateTime expiryTime) { + return this.generateAccountSAS(accountSASService, accountSASResourceType, accountSASPermission, expiryTime, + null /* startTime */, null /* version */, null /* ipRange */, null /* sasProtocol */); + } + + /** + * Generates an account SAS token with the specified parameters + * + * @param accountSASService + * The {@code AccountSASService} services for the account SAS + * @param accountSASResourceType + * An optional {@code AccountSASResourceType} resources for the account SAS + * @param accountSASPermission + * The {@code AccountSASPermission} permission for the account SAS + * @param expiryTime + * The {@code OffsetDateTime} expiry time for the account SAS + * @param startTime + * The {@code OffsetDateTime} start time for the account SAS + * @param version + * The {@code String} version for the account SAS + * @param ipRange + * An optional {@code IPRange} ip address range for the SAS + * @param sasProtocol + * An optional {@code SASProtocol} protocol for the SAS + * + * @return + * A string that represents the SAS token + */ + public String generateAccountSAS(AccountSASService accountSASService, AccountSASResourceType accountSASResourceType, + AccountSASPermission accountSASPermission, OffsetDateTime expiryTime, OffsetDateTime startTime, String version, IPRange ipRange, + SASProtocol sasProtocol) { + + AccountSASSignatureValues accountSASSignatureValues = new AccountSASSignatureValues(); + accountSASSignatureValues.services(accountSASService == null ? null : accountSASService.toString()); + accountSASSignatureValues.resourceTypes(accountSASResourceType == null ? null : accountSASResourceType.toString()); + accountSASSignatureValues.permissions(accountSASPermission == null ? null : accountSASPermission.toString()); + accountSASSignatureValues.expiryTime(expiryTime); + accountSASSignatureValues.startTime(startTime); + + if (version != null) { + accountSASSignatureValues.version(version); + } + + accountSASSignatureValues.ipRange(ipRange); + accountSASSignatureValues.protocol(sasProtocol); + + SharedKeyCredential sharedKeyCredential = Utility.getSharedKeyCredential(this.storageAsyncRawClient.azureBlobStorage.httpPipeline()); + + SASQueryParameters sasQueryParameters = accountSASSignatureValues.generateSASQueryParameters(sharedKeyCredential); + + return sasQueryParameters.encode(); + } } diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/StorageClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/StorageClient.java index f18cf0640fbd9..c895cdda58bbc 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/StorageClient.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/StorageClient.java @@ -290,4 +290,53 @@ public Response getAccountInfo(Duration timeout) { return Utility.blockWithOptionalTimeout(response, timeout); } + + /** + * Generates an account SAS token with the specified parameters + * + * @param accountSASService + * The {@code AccountSASService} services for the account SAS + * @param accountSASResourceType + * An optional {@code AccountSASResourceType} resources for the account SAS + * @param accountSASPermission + * The {@code AccountSASPermission} permission for the account SAS + * @param expiryTime + * The {@code OffsetDateTime} expiry time for the account SAS + * + * @return + * A string that represents the SAS token + */ + public String generateAccountSAS(AccountSASService accountSASService, AccountSASResourceType accountSASResourceType, + AccountSASPermission accountSASPermission, OffsetDateTime expiryTime) { + return this.storageAsyncClient.generateAccountSAS(accountSASService, accountSASResourceType, accountSASPermission, expiryTime); + } + + /** + * Generates an account SAS token with the specified parameters + * + * @param accountSASService + * The {@code AccountSASService} services for the account SAS + * @param accountSASResourceType + * An optional {@code AccountSASResourceType} resources for the account SAS + * @param accountSASPermission + * The {@code AccountSASPermission} permission for the account SAS + * @param expiryTime + * The {@code OffsetDateTime} expiry time for the account SAS + * @param startTime + * The {@code OffsetDateTime} start time for the account SAS + * @param version + * The {@code String} version for the account SAS + * @param ipRange + * An optional {@code IPRange} ip address range for the SAS + * @param sasProtocol + * An optional {@code SASProtocol} protocol for the SAS + * + * @return + * A string that represents the SAS token + */ + public String generateAccountSAS(AccountSASService accountSASService, AccountSASResourceType accountSASResourceType, + AccountSASPermission accountSASPermission, OffsetDateTime expiryTime, OffsetDateTime startTime, String version, IPRange ipRange, + SASProtocol sasProtocol) { + return this.storageAsyncClient.generateAccountSAS(accountSASService, accountSASResourceType, accountSASPermission, expiryTime, startTime, version, ipRange, sasProtocol); + } } diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/Utility.java b/storage/client/blob/src/main/java/com/azure/storage/blob/Utility.java index 3b5d073c4023e..252a5e83bbaf2 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/Utility.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/Utility.java @@ -5,9 +5,13 @@ import com.azure.core.http.HttpHeader; import com.azure.core.http.HttpHeaders; +import com.azure.core.http.HttpPipeline; +import com.azure.core.http.policy.HttpPipelinePolicy; import com.azure.core.implementation.http.UrlBuilder; import com.azure.storage.blob.models.StorageErrorException; import com.azure.storage.blob.models.UserDelegationKey; +import com.azure.storage.common.credentials.SharedKeyCredential; +import com.azure.storage.common.policy.SharedKeyCredentialPolicy; import reactor.core.publisher.Mono; import reactor.util.annotation.Nullable; @@ -387,4 +391,23 @@ static T blockWithOptionalTimeout(Mono response, @Nullable Duration timeo return response.block(timeout); } } + + /** + * Gets the SharedKeyCredential from the HttpPipeline + * + * @param httpPipeline + * The {@code HttpPipeline} httpPipeline from which a sharedKeyCredential will be extracted + * + * @return The {@code SharedKeyCredential} sharedKeyCredential in the httpPipeline + */ + static SharedKeyCredential getSharedKeyCredential(HttpPipeline httpPipeline) { + for (int i = 0; i < httpPipeline.getPolicyCount(); i++) { + HttpPipelinePolicy httpPipelinePolicy = httpPipeline.getPolicy(i); + if (httpPipelinePolicy instanceof SharedKeyCredentialPolicy) { + SharedKeyCredentialPolicy sharedKeyCredentialPolicy = (SharedKeyCredentialPolicy) httpPipelinePolicy; + return sharedKeyCredentialPolicy.sharedKeyCredential(); + } + } + return null; + } } diff --git a/storage/client/blob/src/main/java/com/azure/storage/common/credentials/SASTokenCredential.java b/storage/client/blob/src/main/java/com/azure/storage/common/credentials/SASTokenCredential.java index fe93273e3f64e..4dce1c831ce21 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/common/credentials/SASTokenCredential.java +++ b/storage/client/blob/src/main/java/com/azure/storage/common/credentials/SASTokenCredential.java @@ -18,12 +18,27 @@ public final class SASTokenCredential { private static final String SIGNED_PERMISSIONS = "sp"; private static final String SIGNED_EXPIRY = "se"; private static final String SIGNATURE = "sig"; + private static final String SIGNED_RESOURCE = "sr"; // Optional SAS token pieces private static final String SIGNED_START = "st"; private static final String SIGNED_PROTOCOL = "spr"; private static final String SIGNED_IP = "sip"; + private static final String CACHE_CONTROL = "rscc"; + private static final String CONTENT_DISPOSITION = "rscd"; + private static final String CONTENT_ENCODING = "rsce"; + private static final String CONTENT_LANGUAGE = "rscl"; + private static final String CONTENT_TYPE = "rsct"; + + // Possible User Delegation Key pieces + private static final String SIGNED_KEY_O_ID = "skoid"; + private static final String SIGNED_KEY_T_ID = "sktid"; + private static final String SIGNED_KEY_START = "skt"; + private static final String SIGNED_KEY_EXPIRY = "ske"; + private static final String SIGNED_KEY_SERVICE = "sks"; + private static final String SIGNED_KEY_VERSION = "skv"; + private final String sasToken; /** @@ -57,20 +72,34 @@ public static SASTokenCredential fromQuery(String query) { queryParams.put(key, queryParam); } - if (queryParams.size() < 6 - || !queryParams.containsKey(SIGNED_VERSION) - || !queryParams.containsKey(SIGNED_SERVICES) - || !queryParams.containsKey(SIGNED_RESOURCE_TYPES) - || !queryParams.containsKey(SIGNED_PERMISSIONS) - || !queryParams.containsKey(SIGNED_EXPIRY) - || !queryParams.containsKey(SIGNATURE)) { + /* Because ServiceSAS only requires expiry and permissions, both of which could be on the container + acl, the only guaranteed indication of a SAS is the signature. We'll let the service validate + the other query parameters. */ + if (!queryParams.containsKey(SIGNATURE)) { return null; } - StringBuilder sasTokenBuilder = new StringBuilder(queryParams.get(SIGNED_VERSION)) - .append("&").append(queryParams.get(SIGNED_SERVICES)) - .append("&").append(queryParams.get(SIGNED_RESOURCE_TYPES)) - .append("&").append(queryParams.get(SIGNED_PERMISSIONS)); + StringBuilder sasTokenBuilder = new StringBuilder(); + + if (queryParams.containsKey(SIGNED_VERSION)) { + sasTokenBuilder.append(queryParams.get(SIGNED_VERSION)); + } + + if (queryParams.containsKey(SIGNED_SERVICES)) { + sasTokenBuilder.append("&").append(queryParams.get(SIGNED_SERVICES)); + } + + if (queryParams.containsKey(SIGNED_RESOURCE_TYPES)) { + sasTokenBuilder.append("&").append(queryParams.get(SIGNED_RESOURCE_TYPES)); + } + + if (queryParams.containsKey(SIGNED_PERMISSIONS)) { + sasTokenBuilder.append("&").append(queryParams.get(SIGNED_PERMISSIONS)); + } + + if (queryParams.containsKey(SIGNED_RESOURCE)) { + sasTokenBuilder.append("&").append(queryParams.get(SIGNED_RESOURCE)); + } // SIGNED_START is optional if (queryParams.containsKey(SIGNED_START)) { @@ -89,6 +118,51 @@ public static SASTokenCredential fromQuery(String query) { sasTokenBuilder.append("&").append(queryParams.get(SIGNED_PROTOCOL)); } + if (queryParams.containsKey(CACHE_CONTROL)) { + sasTokenBuilder.append("&").append(queryParams.get(CACHE_CONTROL)); + } + + if (queryParams.containsKey(CONTENT_DISPOSITION)) { + sasTokenBuilder.append("&").append(queryParams.get(CONTENT_DISPOSITION)); + } + + if (queryParams.containsKey(CONTENT_ENCODING)) { + sasTokenBuilder.append("&").append(queryParams.get(CONTENT_ENCODING)); + } + + if (queryParams.containsKey(CONTENT_LANGUAGE)) { + sasTokenBuilder.append("&").append(queryParams.get(CONTENT_LANGUAGE)); + } + + if (queryParams.containsKey(CONTENT_TYPE)) { + sasTokenBuilder.append("&").append(queryParams.get(CONTENT_TYPE)); + } + + // User Delegation Key Parameters + if (queryParams.containsKey(SIGNED_KEY_O_ID)) { + sasTokenBuilder.append("&").append(queryParams.get(SIGNED_KEY_O_ID)); + } + + if (queryParams.containsKey(SIGNED_KEY_T_ID)) { + sasTokenBuilder.append("&").append(queryParams.get(SIGNED_KEY_T_ID)); + } + + if (queryParams.containsKey(SIGNED_KEY_START)) { + sasTokenBuilder.append("&").append(queryParams.get(SIGNED_KEY_START)); + } + + if (queryParams.containsKey(SIGNED_KEY_EXPIRY)) { + sasTokenBuilder.append("&").append(queryParams.get(SIGNED_KEY_EXPIRY)); + } + + if (queryParams.containsKey(SIGNED_KEY_SERVICE)) { + sasTokenBuilder.append("&").append(queryParams.get(SIGNED_KEY_SERVICE)); + } + + if (queryParams.containsKey(SIGNED_KEY_VERSION)) { + sasTokenBuilder.append("&").append(queryParams.get(SIGNED_KEY_VERSION)); + } + sasTokenBuilder.append("&").append(queryParams.get(SIGNATURE)); return new SASTokenCredential(sasTokenBuilder.toString()); diff --git a/storage/client/blob/src/main/java/com/azure/storage/common/policy/SharedKeyCredentialPolicy.java b/storage/client/blob/src/main/java/com/azure/storage/common/policy/SharedKeyCredentialPolicy.java index 8ee1284591dd2..743eae8f262e4 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/common/policy/SharedKeyCredentialPolicy.java +++ b/storage/client/blob/src/main/java/com/azure/storage/common/policy/SharedKeyCredentialPolicy.java @@ -24,6 +24,15 @@ public SharedKeyCredentialPolicy(SharedKeyCredential credential) { this.credential = credential; } + /** + * Gets the shared key credential linked to the policy. + * @return + * The {@link SharedKeyCredential} linked to the policy. + */ + public SharedKeyCredential sharedKeyCredential() { + return this.credential; + } + @Override public Mono process(HttpPipelineCallContext context, HttpPipelineNextPolicy next) { String authorizationValue = credential.generateAuthorizationHeader(context.httpRequest().url(), diff --git a/storage/client/blob/src/test/java/com/azure/storage/blob/SASTest.groovy b/storage/client/blob/src/test/java/com/azure/storage/blob/SASTest.groovy new file mode 100644 index 0000000000000..1ebf9860f2ac3 --- /dev/null +++ b/storage/client/blob/src/test/java/com/azure/storage/blob/SASTest.groovy @@ -0,0 +1,1079 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.storage.blob + +import com.azure.storage.blob.models.AccessPolicy +import com.azure.storage.blob.models.BlobRange +import com.azure.storage.blob.models.SignedIdentifier +import com.azure.storage.blob.models.StorageErrorCode +import com.azure.storage.blob.models.UserDelegationKey +import com.azure.storage.common.credentials.SASTokenCredential +import com.azure.storage.common.credentials.SharedKeyCredential +import spock.lang.Unroll + +import java.time.LocalDateTime +import java.time.OffsetDateTime +import java.time.ZoneOffset + +class SASTest extends APISpec { + + def "responseError"() { + when: + cu.listBlobsFlat() + + then: + def e = thrown(StorageException) + e.errorCode() == StorageErrorCode.INVALID_QUERY_PARAMETER_VALUE + e.statusCode() == 400 + e.message().contains("Value for one of the query parameters specified in the request URI is invalid.") + e.getMessage().contains(" Date: Tue, 16 Jul 2019 10:48:17 -0700 Subject: [PATCH 02/17] Remove RawClients from Blobs (#4375) Removes RawClients from Storage Blobs --- .../storage/blob/AppendBlobAsyncClient.java | 47 +- .../blob/AppendBlobAsyncRawClient.java | 192 ---- .../azure/storage/blob/AppendBlobClient.java | 17 +- .../azure/storage/blob/BlobAsyncClient.java | 830 +++++++-------- .../storage/blob/BlobAsyncRawClient.java | 766 -------------- .../com/azure/storage/blob/BlobClient.java | 680 +++++-------- .../azure/storage/blob/BlobInputStream.java | 2 +- .../azure/storage/blob/BlobOutputStream.java | 4 +- .../com/azure/storage/blob/BlobURLParts.java | 8 +- .../storage/blob/BlockBlobAsyncClient.java | 50 +- .../storage/blob/BlockBlobAsyncRawClient.java | 364 ------- .../azure/storage/blob/BlockBlobClient.java | 14 +- .../storage/blob/ContainerAsyncClient.java | 955 +++++++++--------- .../storage/blob/ContainerAsyncRawClient.java | 708 ------------- .../azure/storage/blob/ContainerClient.java | 660 +++++------- .../storage/blob/ContainerRawClient.java | 652 ------------ .../storage/blob/PageBlobAsyncClient.java | 210 +++- .../storage/blob/PageBlobAsyncRawClient.java | 620 ------------ .../azure/storage/blob/PageBlobClient.java | 12 +- .../blob/ServiceSASSignatureValues.java | 111 +- .../storage/blob/StorageAsyncClient.java | 222 ++-- .../storage/blob/StorageAsyncRawClient.java | 172 ---- .../com/azure/storage/blob/StorageClient.java | 197 ++-- .../azure/storage/blob/StorageRawClient.java | 259 ----- .../credentials/SASTokenCredential.java | 2 + .../policy/SharedKeyCredentialPolicy.java | 5 +- .../java/com/azure/storage/blob/Sample.java | 6 +- 27 files changed, 1885 insertions(+), 5880 deletions(-) delete mode 100644 storage/client/blob/src/main/java/com/azure/storage/blob/AppendBlobAsyncRawClient.java delete mode 100644 storage/client/blob/src/main/java/com/azure/storage/blob/BlobAsyncRawClient.java delete mode 100644 storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobAsyncRawClient.java delete mode 100644 storage/client/blob/src/main/java/com/azure/storage/blob/ContainerAsyncRawClient.java delete mode 100644 storage/client/blob/src/main/java/com/azure/storage/blob/ContainerRawClient.java delete mode 100644 storage/client/blob/src/main/java/com/azure/storage/blob/PageBlobAsyncRawClient.java delete mode 100644 storage/client/blob/src/main/java/com/azure/storage/blob/StorageAsyncRawClient.java delete mode 100644 storage/client/blob/src/main/java/com/azure/storage/blob/StorageRawClient.java diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/AppendBlobAsyncClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/AppendBlobAsyncClient.java index 7b4585580e16f..60376a3d990ab 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/AppendBlobAsyncClient.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/AppendBlobAsyncClient.java @@ -5,6 +5,7 @@ import com.azure.core.http.rest.Response; import com.azure.core.http.rest.SimpleResponse; +import com.azure.core.util.Context; import com.azure.storage.blob.implementation.AzureBlobStorageBuilder; import com.azure.storage.blob.models.AppendBlobAccessConditions; import com.azure.storage.blob.models.AppendBlobItem; @@ -13,12 +14,13 @@ import com.azure.storage.blob.models.BlobRange; import com.azure.storage.blob.models.Metadata; import com.azure.storage.blob.models.SourceModifiedAccessConditions; -import io.netty.buffer.Unpooled; +import io.netty.buffer.ByteBuf; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.net.URL; -import java.nio.ByteBuffer; + +import static com.azure.storage.blob.Utility.postProcessResponse; /** @@ -45,8 +47,6 @@ * object through {@link Mono#toFuture()}. */ public final class AppendBlobAsyncClient extends BlobAsyncClient { - final AppendBlobAsyncRawClient appendBlobAsyncRawClient; - /** * Indicates the maximum number of bytes that can be sent in a call to appendBlock. */ @@ -63,7 +63,6 @@ public final class AppendBlobAsyncClient extends BlobAsyncClient { */ AppendBlobAsyncClient(AzureBlobStorageBuilder azureBlobStorageBuilder, String snapshot) { super(azureBlobStorageBuilder, snapshot); - appendBlobAsyncRawClient = new AppendBlobAsyncRawClient(azureBlobStorageBuilder.build()); } /** @@ -90,8 +89,13 @@ public Mono> create() { * A reactive response containing the information of the created appended blob. */ public Mono> create(BlobHTTPHeaders headers, Metadata metadata, BlobAccessConditions accessConditions) { - return appendBlobAsyncRawClient - .create(headers, metadata, accessConditions) + metadata = (metadata == null) ? new Metadata() : metadata; + accessConditions = (accessConditions == null) ? new BlobAccessConditions() : accessConditions; + + return postProcessResponse(this.azureBlobStorage.appendBlobs().createWithRestResponseAsync(null, + null, 0, null, metadata, null, null, + null, null, headers, accessConditions.leaseAccessConditions(), + accessConditions.modifiedAccessConditions(), Context.NONE)) .map(rb -> new SimpleResponse<>(rb, new AppendBlobItem(rb.deserializedHeaders()))); } @@ -111,7 +115,7 @@ public Mono> create(BlobHTTPHeaders headers, Metadata m * @return * A reactive response containing the information of the append blob operation. */ - public Mono> appendBlock(Flux data, long length) { + public Mono> appendBlock(Flux data, long length) { return this.appendBlock(data, length, null); } @@ -133,10 +137,17 @@ public Mono> appendBlock(Flux data, long le * @return * A reactive response containing the information of the append blob operation. */ - public Mono> appendBlock(Flux data, long length, - AppendBlobAccessConditions appendBlobAccessConditions) { - return appendBlobAsyncRawClient - .appendBlock(data.map(Unpooled::wrappedBuffer), length, appendBlobAccessConditions) + public Mono> appendBlock(Flux data, long length, + AppendBlobAccessConditions appendBlobAccessConditions) { + appendBlobAccessConditions = appendBlobAccessConditions == null ? new AppendBlobAccessConditions() + : appendBlobAccessConditions; + + return postProcessResponse(this.azureBlobStorage.appendBlobs().appendBlockWithRestResponseAsync( + null, null, data, length, null, null, + null, null, null, null, + appendBlobAccessConditions.leaseAccessConditions(), + appendBlobAccessConditions.appendPositionAccessConditions(), + appendBlobAccessConditions.modifiedAccessConditions(), Context.NONE)) .map(rb -> new SimpleResponse<>(rb, new AppendBlobItem(rb.deserializedHeaders()))); } @@ -183,8 +194,16 @@ public Mono> appendBlockFromUrl(URL sourceURL, BlobRang public Mono> appendBlockFromUrl(URL sourceURL, BlobRange sourceRange, byte[] sourceContentMD5, AppendBlobAccessConditions destAccessConditions, SourceModifiedAccessConditions sourceAccessConditions) { - return appendBlobAsyncRawClient - .appendBlockFromUrl(sourceURL, sourceRange, sourceContentMD5, destAccessConditions, sourceAccessConditions) + sourceRange = sourceRange == null ? new BlobRange(0) : sourceRange; + destAccessConditions = destAccessConditions == null + ? new AppendBlobAccessConditions() : destAccessConditions; + + return postProcessResponse( + this.azureBlobStorage.appendBlobs().appendBlockFromUrlWithRestResponseAsync(null, null, + sourceURL, 0, sourceRange.toString(), sourceContentMD5, null, null, + destAccessConditions.leaseAccessConditions(), + destAccessConditions.appendPositionAccessConditions(), + destAccessConditions.modifiedAccessConditions(), sourceAccessConditions, Context.NONE)) .map(rb -> new SimpleResponse<>(rb, new AppendBlobItem(rb.deserializedHeaders()))); } } diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/AppendBlobAsyncRawClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/AppendBlobAsyncRawClient.java deleted file mode 100644 index 15bf8e09e4d1f..0000000000000 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/AppendBlobAsyncRawClient.java +++ /dev/null @@ -1,192 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.azure.storage.blob; - -import com.azure.core.util.Context; -import com.azure.storage.blob.implementation.AzureBlobStorageImpl; -import com.azure.storage.blob.models.AppendBlobAccessConditions; -import com.azure.storage.blob.models.AppendBlobsAppendBlockFromUrlResponse; -import com.azure.storage.blob.models.AppendBlobsAppendBlockResponse; -import com.azure.storage.blob.models.AppendBlobsCreateResponse; -import com.azure.storage.blob.models.BlobAccessConditions; -import com.azure.storage.blob.models.BlobHTTPHeaders; -import com.azure.storage.blob.models.BlobRange; -import com.azure.storage.blob.models.Metadata; -import com.azure.storage.blob.models.SourceModifiedAccessConditions; -import io.netty.buffer.ByteBuf; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import java.net.URL; - -import static com.azure.storage.blob.Utility.postProcessResponse; - - -/** - * Represents a URL to an append blob. It may be obtained by direct construction or via the create method on a - * {@link ContainerAsyncClient} object. This class does not hold any state about a particular append blob but is instead a - * convenient way of sending off appropriate requests to the resource on the service. Please refer to the - * Azure Docs - */ -final class AppendBlobAsyncRawClient extends BlobAsyncRawClient { - - /** - * Indicates the maximum number of bytes that can be sent in a call to appendBlock. - */ - public static final int MAX_APPEND_BLOCK_BYTES = 4 * Constants.MB; - - /** - * Indicates the maximum number of blocks allowed in an append blob. - */ - public static final int MAX_BLOCKS = 50000; - - /** - * Creates a {@code AppendBlobAsyncRawClient} object pointing to the account specified by the URL and using the provided - * pipeline to make HTTP requests. - */ - AppendBlobAsyncRawClient(AzureBlobStorageImpl azureBlobStorage) { - super(azureBlobStorage, null); - } - - /** - * Creates a 0-length append blob. Call AppendBlock to append data to an append blob. For more information, see - * the Azure Docs. - * - * @return Emits the successful response. - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=append_blob "Sample code for AppendBlobAsyncRawClient.create")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono create() { - return this.create(null, null, null); - } - - /** - * Creates a 0-length append blob. Call AppendBlock to append data to an append blob. For more information, see - * the Azure Docs. - * - * @param headers {@link BlobHTTPHeaders} - * @param metadata {@link Metadata} - * @param accessConditions {@link BlobAccessConditions} - * @return Emits the successful response. - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=append_blob "Sample code for AppendBlobAsyncRawClient.create")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono create(BlobHTTPHeaders headers, Metadata metadata, - BlobAccessConditions accessConditions) { - metadata = metadata == null ? new Metadata() : metadata; - accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions; - - return postProcessResponse(this.azureBlobStorage.appendBlobs().createWithRestResponseAsync(null, - null, 0, null, metadata, null, null, - null, null, headers, accessConditions.leaseAccessConditions(), - accessConditions.modifiedAccessConditions(), Context.NONE)); - } - - /** - * Commits a new block of data to the end of the existing append blob. For more information, see the - * Azure Docs. - *

- * Note that the data passed must be replayable if retries are enabled (the default). In other words, the - * {@code Flux} must produce the same data each time it is subscribed to. - * - * @param data The data to write to the blob. Note that this {@code Flux} must be replayable if retries are enabled - * (the default). In other words, the Flowable must produce the same data each time it is subscribed to. - * @param length The exact length of the data. It is important that this value match precisely the length of the data - * emitted by the {@code Flux}. - * @return Emits the successful response. - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=append_blob "Sample code for AppendBlobAsyncRawClient.appendBlock")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono appendBlock(Flux data, long length) { - return this.appendBlock(data, length, null); - } - - /** - * Commits a new block of data to the end of the existing append blob. For more information, see the - * Azure Docs. - *

- * Note that the data passed must be replayable if retries are enabled (the default). In other words, the - * {@code Flux} must produce the same data each time it is subscribed to. - * - * @param data The data to write to the blob. Note that this {@code Flux} must be replayable if retries are enabled - * (the default). In other words, the Flowable must produce the same data each time it is subscribed to. - * @param length The exact length of the data. It is important that this value match precisely the length of the data - * emitted by the {@code Flux}. - * @param appendBlobAccessConditions {@link AppendBlobAccessConditions} - * @return Emits the successful response. - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=append_blob "Sample code for AppendBlobAsyncRawClient.appendBlock")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono appendBlock(Flux data, long length, - AppendBlobAccessConditions appendBlobAccessConditions) { - appendBlobAccessConditions = appendBlobAccessConditions == null ? new AppendBlobAccessConditions() - : appendBlobAccessConditions; - - return postProcessResponse(this.azureBlobStorage.appendBlobs().appendBlockWithRestResponseAsync( - null, null, data, length, null, null, - null, null, null, null, - appendBlobAccessConditions.leaseAccessConditions(), - appendBlobAccessConditions.appendPositionAccessConditions(), - appendBlobAccessConditions.modifiedAccessConditions(), Context.NONE)); - } - - /** - * Commits a new block of data from another blob to the end of this append blob. For more information, see the - * Azure Docs. - *

- * - * @param sourceURL The url to the blob that will be the source of the copy. A source blob in the same storage account can - * be authenticated via Shared Key. However, if the source is a blob in another account, the source blob - * must either be public or must be authenticated via a shared access signature. If the source blob is - * public, no authentication is required to perform the operation. - * @param sourceRange The source {@link BlobRange} to copy. - * @return Emits the successful response. - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=append_from_url "Sample code for AppendBlobAsyncRawClient.appendBlockFromUrl")] - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono appendBlockFromUrl(URL sourceURL, BlobRange sourceRange) { - return this.appendBlockFromUrl(sourceURL, sourceRange, null, null, - null); - } - - /** - * Commits a new block of data from another blob to the end of this append blob. For more information, see the - * Azure Docs. - *

- * - * @param sourceURL The url to the blob that will be the source of the copy. A source blob in the same storage account can - * be authenticated via Shared Key. However, if the source is a blob in another account, the source blob - * must either be public or must be authenticated via a shared access signature. If the source blob is - * public, no authentication is required to perform the operation. - * @param sourceRange {@link BlobRange} - * @param sourceContentMD5 An MD5 hash of the block content from the source blob. If specified, the service will calculate the MD5 - * of the received data and fail the request if it does not match the provided MD5. - * @param destAccessConditions {@link AppendBlobAccessConditions} - * @param sourceAccessConditions {@link SourceModifiedAccessConditions} - * @return Emits the successful response. - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=append_from_url "Sample code for AppendBlobAsyncRawClient.appendBlockFromUrl")] - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono appendBlockFromUrl(URL sourceURL, BlobRange sourceRange, - byte[] sourceContentMD5, AppendBlobAccessConditions destAccessConditions, - SourceModifiedAccessConditions sourceAccessConditions) { - - sourceRange = sourceRange == null ? new BlobRange(0) : sourceRange; - destAccessConditions = destAccessConditions == null - ? new AppendBlobAccessConditions() : destAccessConditions; - - return postProcessResponse( - this.azureBlobStorage.appendBlobs().appendBlockFromUrlWithRestResponseAsync(null, null, - sourceURL, 0, sourceRange.toString(), sourceContentMD5, null, null, - destAccessConditions.leaseAccessConditions(), - destAccessConditions.appendPositionAccessConditions(), - destAccessConditions.modifiedAccessConditions(), sourceAccessConditions, Context.NONE)); - } -} diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/AppendBlobClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/AppendBlobClient.java index 47a379649659f..6be2bf7f4e5aa 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/AppendBlobClient.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/AppendBlobClient.java @@ -11,13 +11,14 @@ import com.azure.storage.blob.models.BlobRange; import com.azure.storage.blob.models.Metadata; import com.azure.storage.blob.models.SourceModifiedAccessConditions; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.core.scheduler.Schedulers; import java.io.InputStream; import java.net.URL; -import java.nio.ByteBuffer; import java.time.Duration; @@ -37,18 +38,17 @@ * for more information. */ public final class AppendBlobClient extends BlobClient { - - AppendBlobAsyncClient appendBlobAsyncClient; + private AppendBlobAsyncClient appendBlobAsyncClient; /** * Indicates the maximum number of bytes that can be sent in a call to appendBlock. */ - public static final int MAX_APPEND_BLOCK_BYTES = 4 * Constants.MB; + public static final int MAX_APPEND_BLOCK_BYTES = AppendBlobAsyncClient.MAX_APPEND_BLOCK_BYTES; /** * Indicates the maximum number of blocks allowed in an append blob. */ - public static final int MAX_BLOCKS = 50000; + public static final int MAX_BLOCKS = AppendBlobAsyncClient.MAX_BLOCKS; /** * Package-private constructor for use by {@link AppendBlobClientBuilder}. @@ -58,7 +58,7 @@ public final class AppendBlobClient extends BlobClient { super(appendBlobAsyncClient); this.appendBlobAsyncClient = appendBlobAsyncClient; } - + /** * Creates and opens an output stream to write data to the append blob. If the blob already exists on the service, * it will be overwritten. @@ -160,7 +160,7 @@ public Response appendBlock(InputStream data, long length) { */ public Response appendBlock(InputStream data, long length, AppendBlobAccessConditions appendBlobAccessConditions, Duration timeout) { - Flux fbb = Flux.range(0, (int) Math.ceil((double) length / (double) MAX_APPEND_BLOCK_BYTES)) + Flux fbb = Flux.range(0, (int) Math.ceil((double) length / (double) MAX_APPEND_BLOCK_BYTES)) .map(i -> i * MAX_APPEND_BLOCK_BYTES) .concatMap(pos -> Mono.fromCallable(() -> { long count = pos + MAX_APPEND_BLOCK_BYTES > length ? length - pos : MAX_APPEND_BLOCK_BYTES; @@ -169,7 +169,8 @@ public Response appendBlock(InputStream data, long length, while (read < count) { read += data.read(cache, read, (int) count - read); } - return ByteBuffer.wrap(cache); + + return ByteBufAllocator.DEFAULT.buffer((int) count).writeBytes(cache); })); Mono> response = appendBlobAsyncClient.appendBlock(fbb.subscribeOn(Schedulers.elastic()), length, appendBlobAccessConditions); diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobAsyncClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobAsyncClient.java index 5042f9e782af5..2601107aaa0b6 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobAsyncClient.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobAsyncClient.java @@ -9,7 +9,9 @@ import com.azure.core.http.rest.VoidResponse; import com.azure.core.implementation.http.UrlBuilder; import com.azure.core.implementation.util.FluxUtil; +import com.azure.core.util.Context; import com.azure.storage.blob.implementation.AzureBlobStorageBuilder; +import com.azure.storage.blob.implementation.AzureBlobStorageImpl; import com.azure.storage.blob.models.AccessTier; import com.azure.storage.blob.models.BlobAccessConditions; import com.azure.storage.blob.models.BlobHTTPHeaders; @@ -20,6 +22,7 @@ import com.azure.storage.blob.models.Metadata; import com.azure.storage.blob.models.ModifiedAccessConditions; import com.azure.storage.blob.models.ReliableDownloadOptions; +import com.azure.storage.blob.models.SourceModifiedAccessConditions; import com.azure.storage.blob.models.StorageAccountInfo; import com.azure.storage.blob.models.UserDelegationKey; import com.azure.storage.common.credentials.SharedKeyCredential; @@ -41,82 +44,89 @@ import java.util.ArrayList; import java.util.List; +import static com.azure.storage.blob.Utility.postProcessResponse; + /** - * Client to a blob of any type: block, append, or page. It may only be instantiated through a {@link BlobClientBuilder} or via - * the method {@link ContainerAsyncClient#getBlobAsyncClient(String)}. This class does not hold any state about a particular - * blob, but is instead a convenient way of sending appropriate requests to the resource on the service. + * Client to a blob of any type: block, append, or page. It may only be instantiated through a {@link BlobClientBuilder} + * or via the method {@link ContainerAsyncClient#getBlobAsyncClient(String)}. This class does not hold any state about a + * particular blob, but is instead a convenient way of sending appropriate requests to the resource on the service. * *

* This client offers the ability to download blobs. Note that uploading data is specific to each type of blob. Please * refer to the {@link BlockBlobClient}, {@link PageBlobClient}, or {@link AppendBlobClient} for upload options. This - * client can be converted into one of these clients easily through the methods {@link #asBlockBlobAsyncClient}, - * {@link #asPageBlobAsyncClient}, and {@link #asAppendBlobAsyncClient()}. + * client can be converted into one of these clients easily through the methods {@link #asBlockBlobAsyncClient}, {@link + * #asPageBlobAsyncClient}, and {@link #asAppendBlobAsyncClient()}. * *

* This client contains operations on a blob. Operations on a container are available on {@link ContainerAsyncClient}, * and operations on the service are available on {@link StorageAsyncClient}. * *

- * Please refer to the Azure Docs - * for more information. + * Please refer to the Azure + * Docs for more information. * *

- * Note this client is an async client that returns reactive responses from Spring Reactor Core - * project (https://projectreactor.io/). Calling the methods in this client will NOT - * start the actual network operation, until {@code .subscribe()} is called on the reactive response. - * You can simply convert one of these responses to a {@link java.util.concurrent.CompletableFuture} - * object through {@link Mono#toFuture()}. + * Note this client is an async client that returns reactive responses from Spring Reactor Core project + * (https://projectreactor.io/). Calling the methods in this client will NOT start the actual network + * operation, until {@code .subscribe()} is called on the reactive response. You can simply convert one of these + * responses to a {@link java.util.concurrent.CompletableFuture} object through {@link Mono#toFuture()}. */ public class BlobAsyncClient { private static final int BLOB_DEFAULT_DOWNLOAD_BLOCK_SIZE = 4 * Constants.MB; private static final int BLOB_MAX_DOWNLOAD_BLOCK_SIZE = 100 * Constants.MB; - final BlobAsyncRawClient blobAsyncRawClient; + protected final AzureBlobStorageImpl azureBlobStorage; + protected final String snapshot; /** * Package-private constructor for use by {@link BlobClientBuilder}. + * * @param azureBlobStorageBuilder the API client builder for blob storage API */ BlobAsyncClient(AzureBlobStorageBuilder azureBlobStorageBuilder, String snapshot) { - this.blobAsyncRawClient = new BlobAsyncRawClient(azureBlobStorageBuilder.build(), snapshot); + this.azureBlobStorage = azureBlobStorageBuilder.build(); + this.snapshot = snapshot; } /** * Creates a new {@link BlockBlobAsyncClient} to this resource, maintaining configurations. Only do this for blobs * that are known to be block blobs. * - * @return - * A {@link BlockBlobAsyncClient} to this resource. + * @return A {@link BlockBlobAsyncClient} to this resource. */ public BlockBlobAsyncClient asBlockBlobAsyncClient() { - return new BlockBlobAsyncClient(new AzureBlobStorageBuilder().url(getBlobUrl().toString()).pipeline(blobAsyncRawClient.azureBlobStorage.httpPipeline()), blobAsyncRawClient.snapshot); + return new BlockBlobAsyncClient(new AzureBlobStorageBuilder() + .url(getBlobUrl().toString()) + .pipeline(azureBlobStorage.httpPipeline()), snapshot); } /** * Creates a new {@link AppendBlobAsyncClient} to this resource, maintaining configurations. Only do this for blobs * that are known to be append blobs. * - * @return - * A {@link AppendBlobAsyncClient} to this resource. + * @return A {@link AppendBlobAsyncClient} to this resource. */ public AppendBlobAsyncClient asAppendBlobAsyncClient() { - return new AppendBlobAsyncClient(new AzureBlobStorageBuilder().url(getBlobUrl().toString()).pipeline(blobAsyncRawClient.azureBlobStorage.httpPipeline()), blobAsyncRawClient.snapshot); + return new AppendBlobAsyncClient(new AzureBlobStorageBuilder() + .url(getBlobUrl().toString()) + .pipeline(azureBlobStorage.httpPipeline()), snapshot); } /** * Creates a new {@link PageBlobAsyncClient} to this resource, maintaining configurations. Only do this for blobs * that are known to be page blobs. * - * @return - * A {@link PageBlobAsyncClient} to this resource. + * @return A {@link PageBlobAsyncClient} to this resource. */ public PageBlobAsyncClient asPageBlobAsyncClient() { - return new PageBlobAsyncClient(new AzureBlobStorageBuilder().url(getBlobUrl().toString()).pipeline(blobAsyncRawClient.azureBlobStorage.httpPipeline()), blobAsyncRawClient.snapshot); + return new PageBlobAsyncClient(new AzureBlobStorageBuilder() + .url(getBlobUrl().toString()) + .pipeline(azureBlobStorage.httpPipeline()), snapshot); } /** - * Initializes a {@link ContainerAsyncClient} object pointing to the container this blob is in. This method does - * not create a container. It simply constructs the URL to the container and offers access to methods relevant to + * Initializes a {@link ContainerAsyncClient} object pointing to the container this blob is in. This method does not + * create a container. It simply constructs the URL to the container and offers access to methods relevant to * containers. * * @return A {@link ContainerAsyncClient} object pointing to the container containing the blob @@ -125,31 +135,31 @@ public ContainerAsyncClient getContainerAsyncClient() { BlobURLParts parts = URLParser.parse(getBlobUrl()); return new ContainerAsyncClient(new AzureBlobStorageBuilder() .url(String.format("%s://%s/%s", parts.scheme(), parts.host(), parts.containerName())) - .pipeline(blobAsyncRawClient.azureBlobStorage.httpPipeline())); + .pipeline(azureBlobStorage.httpPipeline())); } /** * Gets the URL of the blob represented by this client. + * * @return the URL. * @throws RuntimeException If the blob is using a malformed URL. */ public URL getBlobUrl() { try { - UrlBuilder urlBuilder = UrlBuilder.parse(blobAsyncRawClient.azureBlobStorage.url()); - if (blobAsyncRawClient.snapshot != null) { - urlBuilder.query("snapshot=" + blobAsyncRawClient.snapshot); + UrlBuilder urlBuilder = UrlBuilder.parse(azureBlobStorage.url()); + if (snapshot != null) { + urlBuilder.query("snapshot=" + snapshot); } return urlBuilder.toURL(); } catch (MalformedURLException e) { - throw new RuntimeException(String.format("Invalid URL on %s: %s" + getClass().getSimpleName(), blobAsyncRawClient.azureBlobStorage.url()), e); + throw new RuntimeException(String.format("Invalid URL on %s: %s" + getClass().getSimpleName(), azureBlobStorage.url()), e); } } /** * Gets if the blob this client represents exists in the cloud. * - * @return - * true if the blob exists, false if it doesn't + * @return true if the blob exists, false if it doesn't */ public Mono> exists() { return this.getProperties() @@ -164,11 +174,8 @@ public Mono> exists() { * Copies the data at the source URL to a blob. For more information, see the * Azure Docs * - * @param sourceURL - * The source URL to copy from. URLs outside of Azure may only be copied to block blobs. - * - * @return - * A reactive response containing the copy ID for the long running operation. + * @param sourceURL The source URL to copy from. URLs outside of Azure may only be copied to block blobs. + * @return A reactive response containing the copy ID for the long running operation. */ public Mono> startCopyFromURL(URL sourceURL) { return this.startCopyFromURL(sourceURL, null, null, null); @@ -178,37 +185,41 @@ public Mono> startCopyFromURL(URL sourceURL) { * Copies the data at the source URL to a blob. For more information, see the * Azure Docs * - * @param sourceURL - * The source URL to copy from. URLs outside of Azure may only be copied to block blobs. - * @param metadata - * {@link Metadata} - * @param sourceModifiedAccessConditions - * {@link ModifiedAccessConditions} against the source. Standard HTTP Access conditions related to the - * modification of data. ETag and LastModifiedTime are used to construct conditions related to when the blob - * was changed relative to the given request. The request will fail if the specified condition is not - * satisfied. - * @param destAccessConditions - * {@link BlobAccessConditions} against the destination. - * - * @return - * A reactive response containing the copy ID for the long running operation. + * @param sourceURL The source URL to copy from. URLs outside of Azure may only be copied to block blobs. + * @param metadata {@link Metadata} + * @param sourceModifiedAccessConditions {@link ModifiedAccessConditions} against the source. Standard HTTP Access + * conditions related to the modification of data. ETag and LastModifiedTime are used to construct conditions + * related to when the blob was changed relative to the given request. The request will fail if the specified + * condition is not satisfied. + * @param destAccessConditions {@link BlobAccessConditions} against the destination. + * @return A reactive response containing the copy ID for the long running operation. */ public Mono> startCopyFromURL(URL sourceURL, Metadata metadata, - ModifiedAccessConditions sourceModifiedAccessConditions, BlobAccessConditions destAccessConditions) { - return blobAsyncRawClient - .startCopyFromURL(sourceURL, metadata, sourceModifiedAccessConditions, destAccessConditions) + ModifiedAccessConditions sourceModifiedAccessConditions, BlobAccessConditions destAccessConditions) { + metadata = metadata == null ? new Metadata() : metadata; + sourceModifiedAccessConditions = sourceModifiedAccessConditions == null + ? new ModifiedAccessConditions() : sourceModifiedAccessConditions; + destAccessConditions = destAccessConditions == null ? new BlobAccessConditions() : destAccessConditions; + + // We want to hide the SourceAccessConditions type from the user for consistency's sake, so we convert here. + SourceModifiedAccessConditions sourceConditions = new SourceModifiedAccessConditions() + .sourceIfModifiedSince(sourceModifiedAccessConditions.ifModifiedSince()) + .sourceIfUnmodifiedSince(sourceModifiedAccessConditions.ifUnmodifiedSince()) + .sourceIfMatch(sourceModifiedAccessConditions.ifMatch()) + .sourceIfNoneMatch(sourceModifiedAccessConditions.ifNoneMatch()); + + return postProcessResponse(this.azureBlobStorage.blobs().startCopyFromURLWithRestResponseAsync( + null, null, sourceURL, null, metadata, null, sourceConditions, + destAccessConditions.modifiedAccessConditions(), destAccessConditions.leaseAccessConditions(), Context.NONE)) .map(rb -> new SimpleResponse<>(rb, rb.deserializedHeaders().copyId())); } /** * Stops a pending copy that was previously started and leaves a destination blob with 0 length and metadata. * - * @param copyId - * The id of the copy operation to abort. Returned as the {@code copyId} field on the {@link - * BlobStartCopyFromURLHeaders} object. - * - * @return - * A reactive response signalling completion. + * @param copyId The id of the copy operation to abort. Returned as the {@code copyId} field on the {@link + * BlobStartCopyFromURLHeaders} object. + * @return A reactive response signalling completion. */ public Mono abortCopyFromURL(String copyId) { return this.abortCopyFromURL(copyId, null); @@ -217,30 +228,23 @@ public Mono abortCopyFromURL(String copyId) { /** * Stops a pending copy that was previously started and leaves a destination blob with 0 length and metadata. * - * @param copyId - * The id of the copy operation to abort. Returned as the {@code copyId} field on the {@link - * BlobStartCopyFromURLHeaders} object. - * @param leaseAccessConditions - * By setting lease access conditions, requests will fail if the provided lease does not match the active - * lease on the blob. - * - * @return - * A reactive response signalling completion. + * @param copyId The id of the copy operation to abort. Returned as the {@code copyId} field on the {@link + * BlobStartCopyFromURLHeaders} object. + * @param leaseAccessConditions By setting lease access conditions, requests will fail if the provided lease does + * not match the active lease on the blob. + * @return A reactive response signalling completion. */ public Mono abortCopyFromURL(String copyId, LeaseAccessConditions leaseAccessConditions) { - return blobAsyncRawClient - .abortCopyFromURL(copyId, leaseAccessConditions) + return postProcessResponse(this.azureBlobStorage.blobs().abortCopyFromURLWithRestResponseAsync( + null, null, copyId, null, null, leaseAccessConditions, Context.NONE)) .map(VoidResponse::new); } /** * Copies the data at the source URL to a blob and waits for the copy to complete before returning a response. * - * @param copySource - * The source URL to copy from. - * - * @return - * A reactive response containing the copy ID for the long running operation. + * @param copySource The source URL to copy from. + * @return A reactive response containing the copy ID for the long running operation. */ public Mono> copyFromURL(URL copySource) { return this.copyFromURL(copySource, null, null, null); @@ -249,63 +253,110 @@ public Mono> copyFromURL(URL copySource) { /** * Copies the data at the source URL to a blob and waits for the copy to complete before returning a response. * - * @param copySource - * The source URL to copy from. URLs outside of Azure may only be copied to block blobs. - * @param metadata - * {@link Metadata} - * @param sourceModifiedAccessConditions - * {@link ModifiedAccessConditions} against the source. Standard HTTP Access conditions related to the - * modification of data. ETag and LastModifiedTime are used to construct conditions related to when the blob - * was changed relative to the given request. The request will fail if the specified condition is not - * satisfied. - * @param destAccessConditions - * {@link BlobAccessConditions} against the destination. - * - * @return - * A reactive response containing the copy ID for the long running operation. + * @param copySource The source URL to copy from. URLs outside of Azure may only be copied to block blobs. + * @param metadata {@link Metadata} + * @param sourceModifiedAccessConditions {@link ModifiedAccessConditions} against the source. Standard HTTP Access + * conditions related to the modification of data. ETag and LastModifiedTime are used to construct conditions + * related to when the blob was changed relative to the given request. The request will fail if the specified + * condition is not satisfied. + * @param destAccessConditions {@link BlobAccessConditions} against the destination. + * @return A reactive response containing the copy ID for the long running operation. */ public Mono> copyFromURL(URL copySource, Metadata metadata, - ModifiedAccessConditions sourceModifiedAccessConditions, BlobAccessConditions destAccessConditions) { - return blobAsyncRawClient - .syncCopyFromURL(copySource, metadata, sourceModifiedAccessConditions, destAccessConditions) + ModifiedAccessConditions sourceModifiedAccessConditions, BlobAccessConditions destAccessConditions) { + metadata = metadata == null ? new Metadata() : metadata; + sourceModifiedAccessConditions = sourceModifiedAccessConditions == null + ? new ModifiedAccessConditions() : sourceModifiedAccessConditions; + destAccessConditions = destAccessConditions == null ? new BlobAccessConditions() : destAccessConditions; + + // We want to hide the SourceAccessConditions type from the user for consistency's sake, so we convert here. + SourceModifiedAccessConditions sourceConditions = new SourceModifiedAccessConditions() + .sourceIfModifiedSince(sourceModifiedAccessConditions.ifModifiedSince()) + .sourceIfUnmodifiedSince(sourceModifiedAccessConditions.ifUnmodifiedSince()) + .sourceIfMatch(sourceModifiedAccessConditions.ifMatch()) + .sourceIfNoneMatch(sourceModifiedAccessConditions.ifNoneMatch()); + + return postProcessResponse(this.azureBlobStorage.blobs().copyFromURLWithRestResponseAsync( + null, null, copySource, null, metadata, null, sourceConditions, + destAccessConditions.modifiedAccessConditions(), destAccessConditions.leaseAccessConditions(), Context.NONE)) .map(rb -> new SimpleResponse<>(rb, rb.deserializedHeaders().copyId())); } /** - * Reads the entire blob. Uploading data must be done from the {@link BlockBlobClient}, {@link PageBlobClient}, or {@link AppendBlobClient}. + * Reads the entire blob. Uploading data must be done from the {@link BlockBlobClient}, {@link PageBlobClient}, or + * {@link AppendBlobClient}. * - * @return - * A reactive response containing the blob data. + * @return A reactive response containing the blob data. */ public Mono>> download() { return this.download(null, null, false, null); } /** - * Reads a range of bytes from a blob. Uploading data must be done from the {@link BlockBlobClient}, {@link PageBlobClient}, or {@link AppendBlobClient}. + * Reads a range of bytes from a blob. Uploading data must be done from the {@link BlockBlobClient}, {@link + * PageBlobClient}, or {@link AppendBlobClient}. * - * @param range - * {@link BlobRange} - * @param accessConditions - * {@link BlobAccessConditions} - * @param rangeGetContentMD5 - * Whether the contentMD5 for the specified blob range should be returned. + * @param range {@link BlobRange} + * @param accessConditions {@link BlobAccessConditions} + * @param rangeGetContentMD5 Whether the contentMD5 for the specified blob range should be returned. * @param options {@link ReliableDownloadOptions} - * * @return A reactive response containing the blob data. */ public Mono>> download(BlobRange range, BlobAccessConditions accessConditions, - boolean rangeGetContentMD5, ReliableDownloadOptions options) { - return blobAsyncRawClient - .download(range, accessConditions, rangeGetContentMD5) + boolean rangeGetContentMD5, ReliableDownloadOptions options) { + return this.download(range, accessConditions, rangeGetContentMD5) .map(response -> new SimpleResponse<>( response.rawResponse(), response.body(options).map(ByteBuf::nioBuffer).switchIfEmpty(Flux.just(ByteBuffer.allocate(0))))); } + /** + * Reads a range of bytes from a blob. The response also includes the blob's properties and metadata. For more + * information, see the Azure Docs. + *

+ * Note that the response body has reliable download functionality built in, meaning that a failed download stream + * will be automatically retried. This behavior may be configured with {@link ReliableDownloadOptions}. + * + * @param range {@link BlobRange} + * @param accessConditions {@link BlobAccessConditions} + * @param rangeGetContentMD5 Whether the contentMD5 for the specified blob range should be returned. + * @return Emits the successful response. + * @apiNote ## Sample Code \n [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=upload_download + * "Sample code for BlobAsyncClient.download")] \n For more samples, please see the [Samples + * file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) + */ + Mono download(BlobRange range, BlobAccessConditions accessConditions, boolean rangeGetContentMD5) { + range = range == null ? new BlobRange(0) : range; + Boolean getMD5 = rangeGetContentMD5 ? rangeGetContentMD5 : null; + accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions; + HTTPGetterInfo info = new HTTPGetterInfo() + .offset(range.offset()) + .count(range.count()) + .eTag(accessConditions.modifiedAccessConditions().ifMatch()); + + // TODO: range is BlobRange but expected as String + // TODO: figure out correct response + return postProcessResponse(this.azureBlobStorage.blobs().downloadWithRestResponseAsync( + null, null, snapshot, null, null, range.toHeaderValue(), getMD5, + null, null, null, null, + accessConditions.leaseAccessConditions(), accessConditions.modifiedAccessConditions(), Context.NONE)) + // Convert the autorest response to a DownloadAsyncResponse, which enable reliable download. + .map(response -> { + // If there wasn't an etag originally specified, lock on the one returned. + info.eTag(response.deserializedHeaders().eTag()); + return new DownloadAsyncResponse(response, info, + // In the event of a stream failure, make a new request to pick up where we left off. + newInfo -> + this.download(new BlobRange(newInfo.offset(), newInfo.count()), + new BlobAccessConditions().modifiedAccessConditions( + new ModifiedAccessConditions().ifMatch(info.eTag())), false)); + }); + } + /** * Downloads the entire blob into a file specified by the path. The file will be created if it doesn't exist. - * Uploading data must be done from the {@link BlockBlobClient}, {@link PageBlobClient}, or {@link AppendBlobClient}. + * Uploading data must be done from the {@link BlockBlobClient}, {@link PageBlobClient}, or {@link + * AppendBlobClient}. *

* This method makes an extra HTTP call to get the length of the blob in the beginning. To avoid this extra call, * use the other overload providing the {@link BlobRange} parameter. @@ -319,21 +370,17 @@ public Mono downloadToFile(String filePath) { /** * Downloads a range of bytes blob into a file specified by the path. The file will be created if it doesn't exist. - * Uploading data must be done from the {@link BlockBlobClient}, {@link PageBlobClient}, or {@link AppendBlobClient}. + * Uploading data must be done from the {@link BlockBlobClient}, {@link PageBlobClient}, or {@link + * AppendBlobClient}. *

* This method makes an extra HTTP call to get the length of the blob in the beginning. To avoid this extra call, * provide the {@link BlobRange} parameter. * - * @param filePath - * A non-null {@link OutputStream} instance where the downloaded data will be written. - * @param range - * {@link BlobRange} - * @param blockSize - * the size of a chunk to download at a time, in bytes - * @param accessConditions - * {@link BlobAccessConditions} - * @param rangeGetContentMD5 - * Whether the contentMD5 for the specified blob range should be returned. + * @param filePath A non-null {@link OutputStream} instance where the downloaded data will be written. + * @param range {@link BlobRange} + * @param blockSize the size of a chunk to download at a time, in bytes + * @param accessConditions {@link BlobAccessConditions} + * @param rangeGetContentMD5 Whether the contentMD5 for the specified blob range should be returned. * @param options {@link ReliableDownloadOptions} * @return An empty response * @throws IllegalArgumentException If {@code blockSize} is less than 0 or greater than 100MB. @@ -349,8 +396,7 @@ public Mono downloadToFile(String filePath, BlobRange range, Integer block channel -> Mono.justOrEmpty(range) .switchIfEmpty(getFullBlobRange(accessConditions)) .flatMapMany(rg -> Flux.fromIterable(sliceBlobRange(rg, blockSize))) - .flatMap(chunk -> blobAsyncRawClient - .download(chunk, accessConditions, rangeGetContentMD5) + .flatMap(chunk -> this.download(chunk, accessConditions, rangeGetContentMD5) .subscribeOn(Schedulers.elastic()) .flatMap(dar -> FluxUtil.bytebufStreamToFile(dar.body(options), channel, chunk.offset() - (range == null ? 0 : range.offset())))) .then(), this::downloadToFileCleanup); @@ -396,8 +442,7 @@ private List sliceBlobRange(BlobRange blobRange, Integer blockSize) { /** * Deletes the specified blob or snapshot. Note that deleting a blob also deletes all its snapshots. * - * @return - * A reactive response signalling completion. + * @return A reactive response signalling completion. */ public Mono delete() { return this.delete(null, null); @@ -406,28 +451,27 @@ public Mono delete() { /** * Deletes the specified blob or snapshot. Note that deleting a blob also deletes all its snapshots. * - * @param deleteBlobSnapshotOptions - * Specifies the behavior for deleting the snapshots on this blob. {@code Include} will delete the base blob - * and all snapshots. {@code Only} will delete only the snapshots. If a snapshot is being deleted, you must - * pass null. - * @param accessConditions - * {@link BlobAccessConditions} - * - * @return - * A reactive response signalling completion. + * @param deleteBlobSnapshotOptions Specifies the behavior for deleting the snapshots on this blob. {@code Include} + * will delete the base blob and all snapshots. {@code Only} will delete only the snapshots. If a snapshot is being + * deleted, you must pass null. + * @param accessConditions {@link BlobAccessConditions} + * @return A reactive response signalling completion. */ public Mono delete(DeleteSnapshotsOptionType deleteBlobSnapshotOptions, - BlobAccessConditions accessConditions) { - return blobAsyncRawClient - .delete(deleteBlobSnapshotOptions, accessConditions) + BlobAccessConditions accessConditions) { + accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions; + + return postProcessResponse(this.azureBlobStorage.blobs().deleteWithRestResponseAsync( + null, null, snapshot, null, null, deleteBlobSnapshotOptions, + null, accessConditions.leaseAccessConditions(), accessConditions.modifiedAccessConditions(), + Context.NONE)) .map(VoidResponse::new); } /** * Returns the blob's metadata and properties. * - * @return - * A reactive response containing the blob properties and metadata. + * @return A reactive response containing the blob properties and metadata. */ public Mono> getProperties() { return this.getProperties(null); @@ -436,93 +480,87 @@ public Mono> getProperties() { /** * Returns the blob's metadata and properties. * - * @param accessConditions - * {@link BlobAccessConditions} - * - * @return - * A reactive response containing the blob properties and metadata. + * @param accessConditions {@link BlobAccessConditions} + * @return A reactive response containing the blob properties and metadata. */ public Mono> getProperties(BlobAccessConditions accessConditions) { - return blobAsyncRawClient - .getProperties(accessConditions) + accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions; + + return postProcessResponse(this.azureBlobStorage.blobs().getPropertiesWithRestResponseAsync( + null, null, snapshot, null, null, null, + null, null, null, accessConditions.leaseAccessConditions(), + accessConditions.modifiedAccessConditions(), Context.NONE)) .map(rb -> new SimpleResponse<>(rb, new BlobProperties(rb.deserializedHeaders()))); } /** - * Changes a blob's HTTP header properties. if only one HTTP header is updated, the - * others will all be erased. In order to preserve existing values, they must be - * passed alongside the header being changed. For more information, see the + * Changes a blob's HTTP header properties. if only one HTTP header is updated, the others will all be erased. In + * order to preserve existing values, they must be passed alongside the header being changed. For more information, + * see the * Azure Docs. * - * @param headers - * {@link BlobHTTPHeaders} - * - * @return - * A reactive response signalling completion. + * @param headers {@link BlobHTTPHeaders} + * @return A reactive response signalling completion. */ public Mono setHTTPHeaders(BlobHTTPHeaders headers) { return this.setHTTPHeaders(headers, null); } /** - * Changes a blob's HTTP header properties. if only one HTTP header is updated, the - * others will all be erased. In order to preserve existing values, they must be - * passed alongside the header being changed. For more information, see the + * Changes a blob's HTTP header properties. if only one HTTP header is updated, the others will all be erased. In + * order to preserve existing values, they must be passed alongside the header being changed. For more information, + * see the * Azure Docs. * - * @param headers - * {@link BlobHTTPHeaders} - * @param accessConditions - * {@link BlobAccessConditions} - * - * @return - * A reactive response signalling completion. + * @param headers {@link BlobHTTPHeaders} + * @param accessConditions {@link BlobAccessConditions} + * @return A reactive response signalling completion. */ public Mono setHTTPHeaders(BlobHTTPHeaders headers, BlobAccessConditions accessConditions) { - return blobAsyncRawClient - .setHTTPHeaders(headers, accessConditions) + accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions; + + return postProcessResponse(this.azureBlobStorage.blobs().setHTTPHeadersWithRestResponseAsync( + null, null, null, null, headers, + accessConditions.leaseAccessConditions(), accessConditions.modifiedAccessConditions(), Context.NONE)) .map(VoidResponse::new); } /** - * Changes a blob's metadata. The specified metadata in this method will replace existing - * metadata. If old values must be preserved, they must be downloaded and included in the - * call to this method. For more information, see the Azure Docs. - * - * @param metadata - * {@link Metadata} + * Changes a blob's metadata. The specified metadata in this method will replace existing metadata. If old values + * must be preserved, they must be downloaded and included in the call to this method. For more information, see the + * Azure Docs. * - * @return - * A reactive response signalling completion. + * @param metadata {@link Metadata} + * @return A reactive response signalling completion. */ public Mono setMetadata(Metadata metadata) { return this.setMetadata(metadata, null); } /** - * Changes a blob's metadata. The specified metadata in this method will replace existing - * metadata. If old values must be preserved, they must be downloaded and included in the - * call to this method. For more information, see the Azure Docs. - * - * @param metadata - * {@link Metadata} - * @param accessConditions - * {@link BlobAccessConditions} + * Changes a blob's metadata. The specified metadata in this method will replace existing metadata. If old values + * must be preserved, they must be downloaded and included in the call to this method. For more information, see the + * Azure Docs. * - * @return - * A reactive response signalling completion. + * @param metadata {@link Metadata} + * @param accessConditions {@link BlobAccessConditions} + * @return A reactive response signalling completion. */ public Mono setMetadata(Metadata metadata, BlobAccessConditions accessConditions) { - return blobAsyncRawClient - .setMetadata(metadata, accessConditions) + metadata = metadata == null ? new Metadata() : metadata; + accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions; + + return postProcessResponse(this.azureBlobStorage.blobs().setMetadataWithRestResponseAsync( + null, null, null, metadata, null, null, + null, null, accessConditions.leaseAccessConditions(), + accessConditions.modifiedAccessConditions(), Context.NONE)) .map(VoidResponse::new); } /** * Creates a read-only snapshot of a blob. * - * @return - * A reactive response containing the ID of the new snapshot. + * @return A reactive response containing the ID of the new snapshot. */ public Mono> createSnapshot() { return this.createSnapshot(null, null); @@ -531,30 +569,29 @@ public Mono> createSnapshot() { /** * Creates a read-only snapshot of a blob. * - * @param metadata - * {@link Metadata} - * @param accessConditions - * {@link BlobAccessConditions} - * - * @return - * A reactive response containing the ID of the new snapshot. + * @param metadata {@link Metadata} + * @param accessConditions {@link BlobAccessConditions} + * @return A reactive response containing the ID of the new snapshot. */ public Mono> createSnapshot(Metadata metadata, BlobAccessConditions accessConditions) { - return blobAsyncRawClient - .createSnapshot(metadata, accessConditions) + metadata = metadata == null ? new Metadata() : metadata; + accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions; + + return postProcessResponse(this.azureBlobStorage.blobs().createSnapshotWithRestResponseAsync( + null, null, null, metadata, null, null, + null, null, accessConditions.modifiedAccessConditions(), + accessConditions.leaseAccessConditions(), Context.NONE)) .map(rb -> new SimpleResponse<>(rb, rb.deserializedHeaders().snapshot())); } /** * Sets the tier on a blob. The operation is allowed on a page blob in a premium storage account or a block blob in * a blob storage or GPV2 account. A premium page blob's tier determines the allowed size, IOPS, and bandwidth of - * the blob. A block blob's tier determines the Hot/Cool/Archive storage type. This does not update the blob's etag. - * - * @param tier - * The new tier for the blob. + * the blob. A block blob's tier determines the Hot/Cool/Archive storage type. This does not update the blob's + * etag. * - * @return - * A reactive response signalling completion. + * @param tier The new tier for the blob. + * @return A reactive response signalling completion. */ public Mono setTier(AccessTier tier) { return this.setTier(tier, null); @@ -563,32 +600,30 @@ public Mono setTier(AccessTier tier) { /** * Sets the tier on a blob. The operation is allowed on a page blob in a premium storage account or a block blob in * a blob storage or GPV2 account. A premium page blob's tier determines the allowed size, IOPS, and bandwidth of - * the blob. A block blob's tier determines the Hot/Cool/Archive storage type. This does not update the blob's etag. + * the blob. A block blob's tier determines the Hot/Cool/Archive storage type. This does not update the blob's + * etag. * - * @param tier - * The new tier for the blob. - * @param leaseAccessConditions - * By setting lease access conditions, requests will fail if the provided lease does not match the active - * lease on the blob. - * - * @return - * A reactive response signalling completion. + * @param tier The new tier for the blob. + * @param leaseAccessConditions By setting lease access conditions, requests will fail if the provided lease does + * not match the active lease on the blob. + * @return A reactive response signalling completion. */ public Mono setTier(AccessTier tier, LeaseAccessConditions leaseAccessConditions) { - return blobAsyncRawClient - .setTier(tier, leaseAccessConditions) + Utility.assertNotNull("tier", tier); + + return postProcessResponse(this.azureBlobStorage.blobs().setTierWithRestResponseAsync( + null, null, tier, null, null, leaseAccessConditions, Context.NONE)) .map(VoidResponse::new); } /** * Undelete restores the content and metadata of a soft-deleted blob and/or any associated soft-deleted snapshots. * - * @return - * A reactive response signalling completion. + * @return A reactive response signalling completion. */ public Mono undelete() { - return blobAsyncRawClient - .undelete() + return postProcessResponse(this.azureBlobStorage.blobs().undeleteWithRestResponseAsync(null, + null, Context.NONE)) .map(VoidResponse::new); } @@ -596,14 +631,10 @@ public Mono undelete() { * Acquires a lease on the blob for write and delete operations. The lease duration must be between 15 to 60 * seconds, or infinite (-1). * - * @param proposedId - * A {@code String} in any valid GUID format. May be null. - * @param duration - * The duration of the lease, in seconds, or negative one (-1) for a lease that - * never expires. A non-infinite lease can be between 15 and 60 seconds. - * - * @return - * A reactive response containing the lease ID. + * @param proposedId A {@code String} in any valid GUID format. May be null. + * @param duration The duration of the lease, in seconds, or negative one (-1) for a lease that never expires. A + * non-infinite lease can be between 15 and 60 seconds. + * @return A reactive response containing the lease ID. */ public Mono> acquireLease(String proposedId, int duration) { return this.acquireLease(proposedId, duration, null); @@ -613,33 +644,33 @@ public Mono> acquireLease(String proposedId, int duration) { * Acquires a lease on the blob for write and delete operations. The lease duration must be between 15 to 60 * seconds, or infinite (-1). * - * @param proposedID - * A {@code String} in any valid GUID format. May be null. - * @param duration - * The duration of the lease, in seconds, or negative one (-1) for a lease that - * never expires. A non-infinite lease can be between 15 and 60 seconds. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * - * @return - * A reactive response containing the lease ID. + * @param proposedID A {@code String} in any valid GUID format. May be null. + * @param duration The duration of the lease, in seconds, or negative one (-1) for a lease that never expires. A + * non-infinite lease can be between 15 and 60 seconds. + * @param modifiedAccessConditions Standard HTTP Access conditions related to the modification of data. ETag and + * LastModifiedTime are used to construct conditions related to when the blob was changed relative to the given + * request. The request will fail if the specified condition is not satisfied. + * @return A reactive response containing the lease ID. + * @throws IllegalArgumentException If {@code duration} is outside the bounds of 15 to 60 or isn't -1. */ public Mono> acquireLease(String proposedID, int duration, ModifiedAccessConditions modifiedAccessConditions) { - return blobAsyncRawClient - .acquireLease(proposedID, duration, modifiedAccessConditions) + if (!(duration == -1 || (duration >= 15 && duration <= 60))) { + // Throwing is preferred to Mono.error because this will error out immediately instead of waiting until + // subscription. + throw new IllegalArgumentException("Duration must be -1 or between 15 and 60."); + } + + return postProcessResponse(this.azureBlobStorage.blobs().acquireLeaseWithRestResponseAsync( + null, null, null, duration, proposedID, null, + modifiedAccessConditions, Context.NONE)) .map(rb -> new SimpleResponse<>(rb, rb.deserializedHeaders().leaseId())); } /** * Renews the blob's previously-acquired lease. * - * @param leaseID - * The leaseId of the active lease on the blob. - * - * @return - * A reactive response containing the renewed lease ID. + * @param leaseID The leaseId of the active lease on the blob. + * @return A reactive response containing the renewed lease ID. */ public Mono> renewLease(String leaseID) { return this.renewLease(leaseID, null); @@ -648,30 +679,23 @@ public Mono> renewLease(String leaseID) { /** * Renews the blob's previously-acquired lease. * - * @param leaseID - * The leaseId of the active lease on the blob. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * - * @return - * A reactive response containing the renewed lease ID. + * @param leaseID The leaseId of the active lease on the blob. + * @param modifiedAccessConditions Standard HTTP Access conditions related to the modification of data. ETag and + * LastModifiedTime are used to construct conditions related to when the blob was changed relative to the given + * request. The request will fail if the specified condition is not satisfied. + * @return A reactive response containing the renewed lease ID. */ public Mono> renewLease(String leaseID, ModifiedAccessConditions modifiedAccessConditions) { - return blobAsyncRawClient - .renewLease(leaseID, modifiedAccessConditions) + return postProcessResponse(this.azureBlobStorage.blobs().renewLeaseWithRestResponseAsync(null, + null, leaseID, null, null, modifiedAccessConditions, Context.NONE)) .map(rb -> new SimpleResponse<>(rb, rb.deserializedHeaders().leaseId())); } /** * Releases the blob's previously-acquired lease. * - * @param leaseID - * The leaseId of the active lease on the blob. - * - * @return - * A reactive response signalling completion. + * @param leaseID The leaseId of the active lease on the blob. + * @return A reactive response signalling completion. */ public Mono releaseLease(String leaseID) { return this.releaseLease(leaseID, null); @@ -680,19 +704,15 @@ public Mono releaseLease(String leaseID) { /** * Releases the blob's previously-acquired lease. * - * @param leaseID - * The leaseId of the active lease on the blob. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * - * @return - * A reactive response signalling completion. + * @param leaseID The leaseId of the active lease on the blob. + * @param modifiedAccessConditions Standard HTTP Access conditions related to the modification of data. ETag and + * LastModifiedTime are used to construct conditions related to when the blob was changed relative to the given + * request. The request will fail if the specified condition is not satisfied. + * @return A reactive response signalling completion. */ public Mono releaseLease(String leaseID, ModifiedAccessConditions modifiedAccessConditions) { - return blobAsyncRawClient - .releaseLease(leaseID, modifiedAccessConditions) + return postProcessResponse(this.azureBlobStorage.blobs().releaseLeaseWithRestResponseAsync(null, + null, leaseID, null, null, modifiedAccessConditions, Context.NONE)) .map(VoidResponse::new); } @@ -700,8 +720,7 @@ public Mono releaseLease(String leaseID, ModifiedAccessConditions * BreakLease breaks the blob's previously-acquired lease (if it exists). Pass the LeaseBreakDefault (-1) constant * to break a fixed-duration lease when it expires or an infinite lease immediately. * - * @return - * A reactive response containing the remaining time in the broken lease in seconds. + * @return A reactive response containing the remaining time in the broken lease in seconds. */ public Mono> breakLease() { return this.breakLease(null, null); @@ -711,90 +730,74 @@ public Mono> breakLease() { * BreakLease breaks the blob's previously-acquired lease (if it exists). Pass the LeaseBreakDefault (-1) constant * to break a fixed-duration lease when it expires or an infinite lease immediately. * - * @param breakPeriodInSeconds - * An optional {@code Integer} representing the proposed duration of seconds that the lease should continue - * before it is broken, between 0 and 60 seconds. This break period is only used if it is shorter than the - * time remaining on the lease. If longer, the time remaining on the lease is used. A new lease will not be - * available before the break period has expired, but the lease may be held for longer than the break - * period. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * - * @return - * A reactive response containing the remaining time in the broken lease in seconds. + * @param breakPeriodInSeconds An optional {@code Integer} representing the proposed duration of seconds that the + * lease should continue before it is broken, between 0 and 60 seconds. This break period is only used if it is + * shorter than the time remaining on the lease. If longer, the time remaining on the lease is used. A new lease + * will not be available before the break period has expired, but the lease may be held for longer than the break + * period. + * @param modifiedAccessConditions Standard HTTP Access conditions related to the modification of data. ETag and + * LastModifiedTime are used to construct conditions related to when the blob was changed relative to the given + * request. The request will fail if the specified condition is not satisfied. + * @return A reactive response containing the remaining time in the broken lease in seconds. */ public Mono> breakLease(Integer breakPeriodInSeconds, ModifiedAccessConditions modifiedAccessConditions) { - return blobAsyncRawClient - .breakLease(breakPeriodInSeconds, modifiedAccessConditions) + return postProcessResponse(this.azureBlobStorage.blobs().breakLeaseWithRestResponseAsync(null, + null, null, breakPeriodInSeconds, null, modifiedAccessConditions, Context.NONE)) .map(rb -> new SimpleResponse<>(rb, rb.deserializedHeaders().leaseTime())); } /** * ChangeLease changes the blob's lease ID. * - * @param leaseId - * The leaseId of the active lease on the blob. - * @param proposedID - * A {@code String} in any valid GUID format. - * - * @return - * A reactive response containing the new lease ID. + * @param leaseId The leaseId of the active lease on the blob. + * @param proposedID A {@code String} in any valid GUID format. + * @return A reactive response containing the new lease ID. */ public Mono> changeLease(String leaseId, String proposedID) { return this.changeLease(leaseId, proposedID, null); } /** - * ChangeLease changes the blob's lease ID. For more information, see the Azure Docs. - * - * @param leaseId - * The leaseId of the active lease on the blob. - * @param proposedID - * A {@code String} in any valid GUID format. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. + * ChangeLease changes the blob's lease ID. For more information, see the Azure + * Docs. * + * @param leaseId The leaseId of the active lease on the blob. + * @param proposedID A {@code String} in any valid GUID format. + * @param modifiedAccessConditions Standard HTTP Access conditions related to the modification of data. ETag and + * LastModifiedTime are used to construct conditions related to when the blob was changed relative to the given + * request. The request will fail if the specified condition is not satisfied. * @return A reactive response containing the new lease ID. */ public Mono> changeLease(String leaseId, String proposedID, ModifiedAccessConditions modifiedAccessConditions) { - return blobAsyncRawClient - .changeLease(leaseId, proposedID, modifiedAccessConditions) + return postProcessResponse(this.azureBlobStorage.blobs().changeLeaseWithRestResponseAsync(null, + null, leaseId, proposedID, null, null, modifiedAccessConditions, Context.NONE)) .map(rb -> new SimpleResponse<>(rb, rb.deserializedHeaders().leaseId())); } /** - * Returns the sku name and account kind for the account. For more information, please see the Azure Docs. + * Returns the sku name and account kind for the account. For more information, please see the Azure Docs. * * @return a reactor response containing the sku name and account kind. */ // TODO (unknown): determine this return type public Mono> getAccountInfo() { - return blobAsyncRawClient - .getAccountInfo() + return postProcessResponse( + this.azureBlobStorage.blobs().getAccountInfoWithRestResponseAsync(null, null, Context.NONE)) .map(rb -> new SimpleResponse<>(rb, new StorageAccountInfo(rb.deserializedHeaders()))); } /** * Generates a user delegation SAS with the specified parameters * - * @param userDelegationKey - * The {@code UserDelegationKey} user delegation key for the SAS - * @param accountName - * The {@code String} account name for the SAS - * @param permissions - * The {@code ContainerSASPermissions} permission for the SAS - * @param expiryTime - * The {@code OffsetDateTime} expiry time for the SAS - * - * @return - * A string that represents the SAS token + * @param userDelegationKey The {@code UserDelegationKey} user delegation key for the SAS + * @param accountName The {@code String} account name for the SAS + * @param permissions The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS + * @return A string that represents the SAS token */ public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, String accountName, - BlobSASPermission permissions, OffsetDateTime expiryTime) { + BlobSASPermission permissions, OffsetDateTime expiryTime) { return this.generateUserDelegationSAS(userDelegationKey, accountName, permissions, expiryTime, null /* startTime */, null /* version */, null /*sasProtocol */, null /* ipRange */, null /* cacheControl */, null /*contentDisposition */, null /* contentEncoding */, null /* contentLanguage */, null /* contentType */); @@ -803,29 +806,19 @@ public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, Str /** * Generates a user delegation SAS token with the specified parameters * - * @param userDelegationKey - * The {@code UserDelegationKey} user delegation key for the SAS - * @param accountName - * The {@code String} account name for the SAS - * @param permissions - * The {@code ContainerSASPermissions} permission for the SAS - * @param expiryTime - * The {@code OffsetDateTime} expiry time for the SAS - * @param startTime - * An optional {@code OffsetDateTime} start time for the SAS - * @param version - * An optional {@code String} version for the SAS - * @param sasProtocol - * An optional {@code SASProtocol} protocol for the SAS - * @param ipRange - * An optional {@code IPRange} ip address range for the SAS - * - * @return - * A string that represents the SAS token + * @param userDelegationKey The {@code UserDelegationKey} user delegation key for the SAS + * @param accountName The {@code String} account name for the SAS + * @param permissions The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS + * @param startTime An optional {@code OffsetDateTime} start time for the SAS + * @param version An optional {@code String} version for the SAS + * @param sasProtocol An optional {@code SASProtocol} protocol for the SAS + * @param ipRange An optional {@code IPRange} ip address range for the SAS + * @return A string that represents the SAS token */ public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, String accountName, - BlobSASPermission permissions, OffsetDateTime expiryTime, OffsetDateTime startTime, String version, - SASProtocol sasProtocol, IPRange ipRange) { + BlobSASPermission permissions, OffsetDateTime expiryTime, OffsetDateTime startTime, String version, + SASProtocol sasProtocol, IPRange ipRange) { return this.generateUserDelegationSAS(userDelegationKey, accountName, permissions, expiryTime, startTime, version, sasProtocol, ipRange, null /* cacheControl */, null /* contentDisposition */, null /* contentEncoding */, null /* contentLanguage */, null /* contentType */); @@ -834,40 +827,25 @@ public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, Str /** * Generates a user delegation SAS token with the specified parameters * - * @param userDelegationKey - * The {@code UserDelegationKey} user delegation key for the SAS - * @param accountName - * The {@code String} account name for the SAS - * @param permissions - * The {@code ContainerSASPermissions} permission for the SAS - * @param expiryTime - * The {@code OffsetDateTime} expiry time for the SAS - * @param startTime - * An optional {@code OffsetDateTime} start time for the SAS - * @param version - * An optional {@code String} version for the SAS - * @param sasProtocol - * An optional {@code SASProtocol} protocol for the SAS - * @param ipRange - * An optional {@code IPRange} ip address range for the SAS - * @param cacheControl - * An optional {@code String} cache-control header for the SAS. - * @param contentDisposition - * An optional {@code String} content-disposition header for the SAS. - * @param contentEncoding - * An optional {@code String} content-encoding header for the SAS. - * @param contentLanguage - * An optional {@code String} content-language header for the SAS. - * @param contentType - * An optional {@code String} content-type header for the SAS. - * - * @return - * A string that represents the SAS token + * @param userDelegationKey The {@code UserDelegationKey} user delegation key for the SAS + * @param accountName The {@code String} account name for the SAS + * @param permissions The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS + * @param startTime An optional {@code OffsetDateTime} start time for the SAS + * @param version An optional {@code String} version for the SAS + * @param sasProtocol An optional {@code SASProtocol} protocol for the SAS + * @param ipRange An optional {@code IPRange} ip address range for the SAS + * @param cacheControl An optional {@code String} cache-control header for the SAS. + * @param contentDisposition An optional {@code String} content-disposition header for the SAS. + * @param contentEncoding An optional {@code String} content-encoding header for the SAS. + * @param contentLanguage An optional {@code String} content-language header for the SAS. + * @param contentType An optional {@code String} content-type header for the SAS. + * @return A string that represents the SAS token */ public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, String accountName, - BlobSASPermission permissions, OffsetDateTime expiryTime, OffsetDateTime startTime, String version, - SASProtocol sasProtocol, IPRange ipRange, String cacheControl, String contentDisposition, - String contentEncoding, String contentLanguage, String contentType) { + BlobSASPermission permissions, OffsetDateTime expiryTime, OffsetDateTime startTime, String version, + SASProtocol sasProtocol, IPRange ipRange, String cacheControl, String contentDisposition, + String contentEncoding, String contentLanguage, String contentType) { ServiceSASSignatureValues serviceSASSignatureValues = new ServiceSASSignatureValues(version, sasProtocol, startTime, expiryTime, permissions == null ? null : permissions.toString(), ipRange, null /* identifier*/, @@ -883,13 +861,9 @@ public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, Str /** * Generates a SAS token with the specified parameters * - * @param permissions - * The {@code ContainerSASPermissions} permission for the SAS - * @param expiryTime - * The {@code OffsetDateTime} expiry time for the SAS - * - * @return - * A string that represents the SAS token + * @param permissions The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS + * @return A string that represents the SAS token */ public String generateSAS(BlobSASPermission permissions, OffsetDateTime expiryTime) { return this.generateSAS(null, permissions, expiryTime, null /* startTime */, /* identifier */ null /* @@ -900,11 +874,8 @@ public String generateSAS(BlobSASPermission permissions, OffsetDateTime expiryTi /** * Generates a SAS token with the specified parameters * - * @param identifier - * The {@code String} name of the access policy on the container this SAS references if any - * - * @return - * A string that represents the SAS token + * @param identifier The {@code String} name of the access policy on the container this SAS references if any + * @return A string that represents the SAS token */ public String generateSAS(String identifier) { return this.generateSAS(identifier, null /* permissions */, null /* expiryTime */, null /* startTime */, @@ -915,26 +886,17 @@ public String generateSAS(String identifier) { /** * Generates a SAS token with the specified parameters * - * @param identifier - * The {@code String} name of the access policy on the container this SAS references if any - * @param permissions - * The {@code ContainerSASPermissions} permission for the SAS - * @param expiryTime - * The {@code OffsetDateTime} expiry time for the SAS - * @param startTime - * An optional {@code OffsetDateTime} start time for the SAS - * @param version - * An optional {@code String} version for the SAS - * @param sasProtocol - * An optional {@code SASProtocol} protocol for the SAS - * @param ipRange - * An optional {@code IPRange} ip address range for the SAS - * - * @return - * A string that represents the SAS token + * @param identifier The {@code String} name of the access policy on the container this SAS references if any + * @param permissions The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS + * @param startTime An optional {@code OffsetDateTime} start time for the SAS + * @param version An optional {@code String} version for the SAS + * @param sasProtocol An optional {@code SASProtocol} protocol for the SAS + * @param ipRange An optional {@code IPRange} ip address range for the SAS + * @return A string that represents the SAS token */ public String generateSAS(String identifier, BlobSASPermission permissions, OffsetDateTime expiryTime, - OffsetDateTime startTime, String version, SASProtocol sasProtocol, IPRange ipRange) { + OffsetDateTime startTime, String version, SASProtocol sasProtocol, IPRange ipRange) { return this.generateSAS(identifier, permissions, expiryTime, startTime, version, sasProtocol, ipRange, null /* cacheControl */, null /* contentLanguage*/, null /* contentEncoding */, null /* contentLanguage */, null /* contentType */); @@ -943,44 +905,30 @@ public String generateSAS(String identifier, BlobSASPermission permissions, Offs /** * Generates a SAS token with the specified parameters * - * @param identifier - * The {@code String} name of the access policy on the container this SAS references if any - * @param permissions - * The {@code ContainerSASPermissions} permission for the SAS - * @param expiryTime - * The {@code OffsetDateTime} expiry time for the SAS - * @param startTime - * An optional {@code OffsetDateTime} start time for the SAS - * @param version - * An optional {@code String} version for the SAS - * @param sasProtocol - * An optional {@code SASProtocol} protocol for the SAS - * @param ipRange - * An optional {@code IPRange} ip address range for the SAS - * @param cacheControl - * An optional {@code String} cache-control header for the SAS. - * @param contentDisposition - * An optional {@code String} content-disposition header for the SAS. - * @param contentEncoding - * An optional {@code String} content-encoding header for the SAS. - * @param contentLanguage - * An optional {@code String} content-language header for the SAS. - * @param contentType - * An optional {@code String} content-type header for the SAS. - * - * @return - * A string that represents the SAS token + * @param identifier The {@code String} name of the access policy on the container this SAS references if any + * @param permissions The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS + * @param startTime An optional {@code OffsetDateTime} start time for the SAS + * @param version An optional {@code String} version for the SAS + * @param sasProtocol An optional {@code SASProtocol} protocol for the SAS + * @param ipRange An optional {@code IPRange} ip address range for the SAS + * @param cacheControl An optional {@code String} cache-control header for the SAS. + * @param contentDisposition An optional {@code String} content-disposition header for the SAS. + * @param contentEncoding An optional {@code String} content-encoding header for the SAS. + * @param contentLanguage An optional {@code String} content-language header for the SAS. + * @param contentType An optional {@code String} content-type header for the SAS. + * @return A string that represents the SAS token */ public String generateSAS(String identifier, BlobSASPermission permissions, OffsetDateTime expiryTime, - OffsetDateTime startTime, String version, SASProtocol sasProtocol, IPRange ipRange, String cacheControl, - String contentDisposition, String contentEncoding, String contentLanguage, String contentType) { + OffsetDateTime startTime, String version, SASProtocol sasProtocol, IPRange ipRange, String cacheControl, + String contentDisposition, String contentEncoding, String contentLanguage, String contentType) { ServiceSASSignatureValues serviceSASSignatureValues = new ServiceSASSignatureValues(version, sasProtocol, startTime, expiryTime, permissions == null ? null : permissions.toString(), ipRange, identifier, cacheControl, contentDisposition, contentEncoding, contentLanguage, contentType); SharedKeyCredential sharedKeyCredential = - Utility.getSharedKeyCredential(this.blobAsyncRawClient.azureBlobStorage.httpPipeline()); + Utility.getSharedKeyCredential(this.azureBlobStorage.httpPipeline()); Utility.assertNotNull("sharedKeyCredential", sharedKeyCredential); @@ -996,10 +944,10 @@ public String generateSAS(String identifier, BlobSASPermission permissions, Offs * Sets serviceSASSignatureValues parameters dependent on the current blob type */ ServiceSASSignatureValues configureServiceSASSignatureValues(ServiceSASSignatureValues serviceSASSignatureValues, - String accountName) { + String accountName) { // Set canonical name - serviceSASSignatureValues.canonicalName(this.blobAsyncRawClient.azureBlobStorage.url(), accountName); + serviceSASSignatureValues.canonicalName(this.azureBlobStorage.url(), accountName); // Set snapshotId serviceSASSignatureValues.snapshotId(getSnapshotId()); @@ -1017,20 +965,18 @@ ServiceSASSignatureValues configureServiceSASSignatureValues(ServiceSASSignature /** * Gets the snapshotId for a blob resource * - * @return - * A string that represents the snapshotId of the snapshot blob + * @return A string that represents the snapshotId of the snapshot blob */ public String getSnapshotId() { - return this.blobAsyncRawClient.snapshot; + return this.snapshot; } /** * Determines if a blob is a snapshot * - * @return - * A boolean that indicates if a blob is a snapshot + * @return A boolean that indicates if a blob is a snapshot */ public boolean isSnapshot() { - return this.blobAsyncRawClient.snapshot != null; + return this.snapshot != null; } } diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobAsyncRawClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobAsyncRawClient.java deleted file mode 100644 index 002ba761a3bf8..0000000000000 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobAsyncRawClient.java +++ /dev/null @@ -1,766 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.azure.storage.blob; - -import com.azure.core.util.Context; -import com.azure.storage.blob.implementation.AzureBlobStorageImpl; -import com.azure.storage.blob.models.AccessTier; -import com.azure.storage.blob.models.BlobAccessConditions; -import com.azure.storage.blob.models.BlobHTTPHeaders; -import com.azure.storage.blob.models.BlobRange; -import com.azure.storage.blob.models.BlobStartCopyFromURLHeaders; -import com.azure.storage.blob.models.BlobsAbortCopyFromURLResponse; -import com.azure.storage.blob.models.BlobsAcquireLeaseResponse; -import com.azure.storage.blob.models.BlobsBreakLeaseResponse; -import com.azure.storage.blob.models.BlobsChangeLeaseResponse; -import com.azure.storage.blob.models.BlobsCopyFromURLResponse; -import com.azure.storage.blob.models.BlobsCreateSnapshotResponse; -import com.azure.storage.blob.models.BlobsDeleteResponse; -import com.azure.storage.blob.models.BlobsGetAccountInfoResponse; -import com.azure.storage.blob.models.BlobsGetPropertiesResponse; -import com.azure.storage.blob.models.BlobsReleaseLeaseResponse; -import com.azure.storage.blob.models.BlobsRenewLeaseResponse; -import com.azure.storage.blob.models.BlobsSetHTTPHeadersResponse; -import com.azure.storage.blob.models.BlobsSetMetadataResponse; -import com.azure.storage.blob.models.BlobsSetTierResponse; -import com.azure.storage.blob.models.BlobsStartCopyFromURLResponse; -import com.azure.storage.blob.models.BlobsUndeleteResponse; -import com.azure.storage.blob.models.DeleteSnapshotsOptionType; -import com.azure.storage.blob.models.LeaseAccessConditions; -import com.azure.storage.blob.models.Metadata; -import com.azure.storage.blob.models.ModifiedAccessConditions; -import com.azure.storage.blob.models.ReliableDownloadOptions; -import com.azure.storage.blob.models.SourceModifiedAccessConditions; -import reactor.core.publisher.Mono; - -import java.net.URL; - -import static com.azure.storage.blob.Utility.postProcessResponse; - -/** - * Represents a URL to a blob of any type: block, append, or page. It may be obtained by direct construction or via the - * create method on a {@link ContainerAsyncClient} object. This class does not hold any state about a particular blob but is - * instead a convenient way of sending off appropriate requests to the resource on the service. Please refer to the - * Azure Docs for more information. - */ -class BlobAsyncRawClient { - - protected AzureBlobStorageImpl azureBlobStorage; - - final String snapshot; - - /** - * Creates a {@code BlobAsyncRawClient} object pointing to the account specified by the URL and using the provided pipeline to - * make HTTP requests.. - */ - BlobAsyncRawClient(AzureBlobStorageImpl azureBlobStorage, String snapshot) { - this.azureBlobStorage = azureBlobStorage; - this.snapshot = snapshot; - } - - /** - * Copies the data at the source URL to a blob. For more information, see the Azure Docs - * - * @param sourceURL - * The source URL to copy from. URLs outside of Azure may only be copied to block blobs. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=start_copy "Sample code for BlobAsyncRawClient.startCopyFromURL")] \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=start_copy_helper "Helper for start_copy sample.")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono startCopyFromURL(URL sourceURL) { - return this.startCopyFromURL(sourceURL, null, null, null); - } - - /** - * Copies the data at the source URL to a blob. For more information, see the Azure Docs - * - * @param sourceURL - * The source URL to copy from. URLs outside of Azure may only be copied to block blobs. - * @param metadata - * {@link Metadata} - * @param sourceModifiedAccessConditions - * {@link ModifiedAccessConditions} against the source. Standard HTTP Access conditions related to the - * modification of data. ETag and LastModifiedTime are used to construct conditions related to when the blob - * was changed relative to the given request. The request will fail if the specified condition is not - * satisfied. - * @param destAccessConditions - * {@link BlobAccessConditions} against the destination. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=start_copy "Sample code for BlobAsyncRawClient.startCopyFromURL")] \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=start_copy_helper "Helper for start_copy sample.")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono startCopyFromURL(URL sourceURL, Metadata metadata, - ModifiedAccessConditions sourceModifiedAccessConditions, BlobAccessConditions destAccessConditions) { - metadata = metadata == null ? new Metadata() : metadata; - sourceModifiedAccessConditions = sourceModifiedAccessConditions == null - ? new ModifiedAccessConditions() : sourceModifiedAccessConditions; - destAccessConditions = destAccessConditions == null ? new BlobAccessConditions() : destAccessConditions; - - // We want to hide the SourceAccessConditions type from the user for consistency's sake, so we convert here. - SourceModifiedAccessConditions sourceConditions = new SourceModifiedAccessConditions() - .sourceIfModifiedSince(sourceModifiedAccessConditions.ifModifiedSince()) - .sourceIfUnmodifiedSince(sourceModifiedAccessConditions.ifUnmodifiedSince()) - .sourceIfMatch(sourceModifiedAccessConditions.ifMatch()) - .sourceIfNoneMatch(sourceModifiedAccessConditions.ifNoneMatch()); - - return postProcessResponse(this.azureBlobStorage.blobs().startCopyFromURLWithRestResponseAsync( - null, null, sourceURL, null, metadata, null, sourceConditions, - destAccessConditions.modifiedAccessConditions(), destAccessConditions.leaseAccessConditions(), Context.NONE)); - } - - /** - * Stops a pending copy that was previously started and leaves a destination blob with 0 length and metadata. For - * more information, see the Azure Docs. - * - * @param copyId - * The id of the copy operation to abort. Returned as the {@code copyId} field on the {@link - * BlobStartCopyFromURLHeaders} object. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=abort_copy "Sample code for BlobAsyncRawClient.abortCopyFromURL")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono abortCopyFromURL(String copyId) { - return this.abortCopyFromURL(copyId, null); - } - - /** - * Stops a pending copy that was previously started and leaves a destination blob with 0 length and metadata. For - * more information, see the Azure Docs. - * - * @param copyId - * The id of the copy operation to abort. Returned as the {@code copyId} field on the {@link - * BlobStartCopyFromURLHeaders} object. - * @param leaseAccessConditions - * By setting lease access conditions, requests will fail if the provided lease does not match the active - * lease on the blob. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=abort_copy "Sample code for BlobAsyncRawClient.abortCopyFromURL")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono abortCopyFromURL(String copyId, - LeaseAccessConditions leaseAccessConditions) { - return postProcessResponse(this.azureBlobStorage.blobs().abortCopyFromURLWithRestResponseAsync( - null, null, copyId, null, null, leaseAccessConditions, Context.NONE)); - } - - /** - * Copies the data at the source URL to a blob and waits for the copy to complete before returning a response. - * For more information, see the Azure Docs - * - * @param copySource - * The source URL to copy from. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=sync_copy "Sample code for BlobAsyncRawClient.copyFromURL")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono syncCopyFromURL(URL copySource) { - return this.syncCopyFromURL(copySource, null, null, null); - } - - /** - * Copies the data at the source URL to a blob and waits for the copy to complete before returning a response. - * For more information, see the Azure Docs - * - * @param copySource - * The source URL to copy from. URLs outside of Azure may only be copied to block blobs. - * @param metadata - * {@link Metadata} - * @param sourceModifiedAccessConditions - * {@link ModifiedAccessConditions} against the source. Standard HTTP Access conditions related to the - * modification of data. ETag and LastModifiedTime are used to construct conditions related to when the blob - * was changed relative to the given request. The request will fail if the specified condition is not - * satisfied. - * @param destAccessConditions - * {@link BlobAccessConditions} against the destination. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=sync_copy "Sample code for BlobAsyncRawClient.copyFromURL")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono syncCopyFromURL(URL copySource, Metadata metadata, - ModifiedAccessConditions sourceModifiedAccessConditions, BlobAccessConditions destAccessConditions) { - metadata = metadata == null ? new Metadata() : metadata; - sourceModifiedAccessConditions = sourceModifiedAccessConditions == null - ? new ModifiedAccessConditions() : sourceModifiedAccessConditions; - destAccessConditions = destAccessConditions == null ? new BlobAccessConditions() : destAccessConditions; - - // We want to hide the SourceAccessConditions type from the user for consistency's sake, so we convert here. - SourceModifiedAccessConditions sourceConditions = new SourceModifiedAccessConditions() - .sourceIfModifiedSince(sourceModifiedAccessConditions.ifModifiedSince()) - .sourceIfUnmodifiedSince(sourceModifiedAccessConditions.ifUnmodifiedSince()) - .sourceIfMatch(sourceModifiedAccessConditions.ifMatch()) - .sourceIfNoneMatch(sourceModifiedAccessConditions.ifNoneMatch()); - - return postProcessResponse(this.azureBlobStorage.blobs().copyFromURLWithRestResponseAsync( - null, null, copySource, null, metadata, null, sourceConditions, - destAccessConditions.modifiedAccessConditions(), destAccessConditions.leaseAccessConditions(), Context.NONE)); - } - - /** - * Reads a range of bytes from a blob. The response also includes the blob's properties and metadata. For more - * information, see the Azure Docs. - *

- * Note that the response body has reliable download functionality built in, meaning that a failed download stream - * will be automatically retried. This behavior may be configured with {@link ReliableDownloadOptions}. - * - * @return Emits the successful response. - * @apiNote ## Sample Code \n [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=upload_download - * "Sample code for BlobAsyncRawClient.download")] \n For more samples, please see the [Samples - * file](%https://github.com/Azure/azure-storage-java/blob/New-Storage-SDK-V10-Preview/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono download() { - return this.download(null, null, false); - } - - /** - * Reads a range of bytes from a blob. The response also includes the blob's properties and metadata. For more - * information, see the Azure Docs. - *

- * Note that the response body has reliable download functionality built in, meaning that a failed download stream - * will be automatically retried. This behavior may be configured with {@link ReliableDownloadOptions}. - * - * @param range - * {@link BlobRange} - * @param accessConditions - * {@link BlobAccessConditions} - * @param rangeGetContentMD5 - * Whether the contentMD5 for the specified blob range should be returned. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=upload_download "Sample code for BlobAsyncRawClient.download")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono download(BlobRange range, BlobAccessConditions accessConditions, - boolean rangeGetContentMD5) { - range = range == null ? new BlobRange(0) : range; - Boolean getMD5 = rangeGetContentMD5 ? rangeGetContentMD5 : null; - accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions; - HTTPGetterInfo info = new HTTPGetterInfo() - .offset(range.offset()) - .count(range.count()) - .eTag(accessConditions.modifiedAccessConditions().ifMatch()); - - // TODO: range is BlobRange but expected as String - // TODO: figure out correct response - return postProcessResponse(this.azureBlobStorage.blobs().downloadWithRestResponseAsync( - null, null, snapshot, null, null, range.toHeaderValue(), getMD5, - null, null, null, null, - accessConditions.leaseAccessConditions(), accessConditions.modifiedAccessConditions(), Context.NONE)) - // Convert the autorest response to a DownloadAsyncResponse, which enable reliable download. - .map(response -> { - // If there wasn't an etag originally specified, lock on the one returned. - info.eTag(response.deserializedHeaders().eTag()); - return new DownloadAsyncResponse(response, info, - // In the event of a stream failure, make a new request to pick up where we left off. - newInfo -> - this.download(new BlobRange(newInfo.offset(), newInfo.count()), - new BlobAccessConditions().modifiedAccessConditions( - new ModifiedAccessConditions().ifMatch(info.eTag())), false)); - }); - } - - /** - * Deletes the specified blob or snapshot. Note that deleting a blob also deletes all its snapshots. For more - * information, see the Azure Docs. - * - * @return Emits the successful response. - * @apiNote ## Sample Code \n [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blob_delete - * "Sample code for BlobAsyncRawClient.delete")] \n For more samples, please see the [Samples - * file](%https://github.com/Azure/azure-storage-java/blob/New-Storage-SDK-V10-Preview/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono delete() { - return this.delete(null, null); - } - - /** - * Deletes the specified blob or snapshot. Note that deleting a blob also deletes all its snapshots. For more - * information, see the Azure Docs. - * - * @param deleteBlobSnapshotOptions - * Specifies the behavior for deleting the snapshots on this blob. {@code Include} will delete the base blob - * and all snapshots. {@code Only} will delete only the snapshots. If a snapshot is being deleted, you must - * pass null. - * @param accessConditions - * {@link BlobAccessConditions} - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blob_delete "Sample code for BlobAsyncRawClient.delete")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono delete(DeleteSnapshotsOptionType deleteBlobSnapshotOptions, - BlobAccessConditions accessConditions) { - accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions; - - return postProcessResponse(this.azureBlobStorage.blobs().deleteWithRestResponseAsync( - null, null, snapshot, null, null, deleteBlobSnapshotOptions, - null, accessConditions.leaseAccessConditions(), accessConditions.modifiedAccessConditions(), - Context.NONE)); - } - - /** - * Returns the blob's metadata and properties. For more information, see the Azure Docs. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=properties_metadata "Sample code for BlobAsyncRawClient.getProperties")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono getProperties() { - return this.getProperties(null); - } - - /** - * Returns the blob's metadata and properties. For more information, see the Azure Docs. - * - * @param accessConditions - * {@link BlobAccessConditions} - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=properties_metadata "Sample code for BlobAsyncRawClient.getProperties")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono getProperties(BlobAccessConditions accessConditions) { - accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions; - - return postProcessResponse(this.azureBlobStorage.blobs().getPropertiesWithRestResponseAsync( - null, null, snapshot, null, null, null, - null, null, null, accessConditions.leaseAccessConditions(), - accessConditions.modifiedAccessConditions(), Context.NONE)); - } - - /** - * Changes a blob's HTTP header properties. For more information, see the Azure - * Docs. - * - * @param headers - * {@link BlobHTTPHeaders} - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=properties_metadata "Sample code for BlobAsyncRawClient.setHTTPHeaders")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono setHTTPHeaders(BlobHTTPHeaders headers) { - return this.setHTTPHeaders(headers, null); - } - - /** - * Changes a blob's HTTP header properties. For more information, see the Azure Docs. - * - * @param headers - * {@link BlobHTTPHeaders} - * @param accessConditions - * {@link BlobAccessConditions} - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=properties_metadata "Sample code for BlobAsyncRawClient.setHTTPHeaders")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono setHTTPHeaders(BlobHTTPHeaders headers, - BlobAccessConditions accessConditions) { - accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions; - - return postProcessResponse(this.azureBlobStorage.blobs().setHTTPHeadersWithRestResponseAsync( - null, null, null, null, headers, - accessConditions.leaseAccessConditions(), accessConditions.modifiedAccessConditions(), Context.NONE)); - } - - /** - * Changes a blob's metadata. For more information, see the Azure Docs. - * - * @param metadata - * {@link Metadata} - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=properties_metadata "Sample code for BlobAsyncRawClient.setMetadata")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono setMetadata(Metadata metadata) { - return this.setMetadata(metadata, null); - } - - /** - * Changes a blob's metadata. For more information, see the Azure Docs. - * - * @param metadata - * {@link Metadata} - * @param accessConditions - * {@link BlobAccessConditions} - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=properties_metadata "Sample code for BlobAsyncRawClient.setMetadata")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono setMetadata(Metadata metadata, BlobAccessConditions accessConditions) { - metadata = metadata == null ? new Metadata() : metadata; - accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions; - - return postProcessResponse(this.azureBlobStorage.blobs().setMetadataWithRestResponseAsync( - null, null, null, metadata, null, null, - null, null, accessConditions.leaseAccessConditions(), - accessConditions.modifiedAccessConditions(), Context.NONE)); - } - - /** - * Creates a read-only snapshot of a blob. For more information, see the Azure Docs. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=snapshot "Sample code for BlobAsyncRawClient.createSnapshot")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono createSnapshot() { - return this.createSnapshot(null, null); - } - - /** - * Creates a read-only snapshot of a blob. For more information, see the Azure Docs. - * - * @param metadata - * {@link Metadata} - * @param accessConditions - * {@link BlobAccessConditions} - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=snapshot "Sample code for BlobAsyncRawClient.createSnapshot")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono createSnapshot(Metadata metadata, BlobAccessConditions accessConditions) { - metadata = metadata == null ? new Metadata() : metadata; - accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions; - - return postProcessResponse(this.azureBlobStorage.blobs().createSnapshotWithRestResponseAsync( - null, null, null, metadata, null, null, - null, null, accessConditions.modifiedAccessConditions(), - accessConditions.leaseAccessConditions(), Context.NONE)); - } - - /** - * Sets the tier on a blob. The operation is allowed on a page blob in a premium storage account or a block blob in - * a blob storage or GPV2 account. A premium page blob's tier determines the allowed size, IOPS, and bandwidth of - * the blob. A block blob's tier determines the Hot/Cool/Archive storage type. This does not update the blob's etag. - *

- * For detailed information about block blob level tiering see the Azure Docs. - * - * @param tier - * The new tier for the blob. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=tier "Sample code for BlobAsyncRawClient.setTier")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono setTier(AccessTier tier) { - return this.setTier(tier, null); - } - - /** - * Sets the tier on a blob. The operation is allowed on a page blob in a premium storage account or a block blob in - * a blob storage or GPV2 account. A premium page blob's tier determines the allowed size, IOPS, and bandwidth of - * the blob. A block blob's tier determines the Hot/Cool/Archive storage type. This does not update the blob's etag. - *

- * For detailed information about block blob level tiering see the Azure Docs. - * - * @param tier - * The new tier for the blob. - * @param leaseAccessConditions - * By setting lease access conditions, requests will fail if the provided lease does not match the active - * lease on the blob. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=tier "Sample code for BlobAsyncRawClient.setTier")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono setTier(AccessTier tier, LeaseAccessConditions leaseAccessConditions) { - Utility.assertNotNull("tier", tier); - - return postProcessResponse(this.azureBlobStorage.blobs().setTierWithRestResponseAsync( - null, null, tier, null, null, leaseAccessConditions, Context.NONE)); - } - - /** - * Undelete restores the content and metadata of a soft-deleted blob and/or any associated soft-deleted snapshots. - * For more information, see the Azure Docs. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=undelete "Sample code for BlobAsyncRawClient.undelete")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono undelete() { - return postProcessResponse(this.azureBlobStorage.blobs().undeleteWithRestResponseAsync(null, - null, Context.NONE)); - } - - /** - * Acquires a lease on the blob for write and delete operations. The lease duration must be between 15 to 60 - * seconds, or infinite (-1). For more information, see the Azure Docs. - * - * @param proposedId - * A {@code String} in any valid GUID format. May be null. - * @param duration - * The duration of the lease, in seconds, or negative one (-1) for a lease that - * never expires. A non-infinite lease can be between 15 and 60 seconds. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blob_lease "Sample code for BlobAsyncRawClient.acquireLease")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono acquireLease(String proposedId, int duration) { - return this.acquireLease(proposedId, duration, null); - } - - /** - * Acquires a lease on the blob for write and delete operations. The lease duration must be between 15 to 60 - * seconds, or infinite (-1). For more information, see the Azure Docs. - * - * @param proposedID - * A {@code String} in any valid GUID format. May be null. - * @param duration - * The duration of the lease, in seconds, or negative one (-1) for a lease that - * never expires. A non-infinite lease can be between 15 and 60 seconds. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * - * @return Emits the successful response. - * @throws IllegalArgumentException If {@code duration} is outside the bounds of 15 to 60 or isn't -1. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blob_lease "Sample code for BlobAsyncRawClient.acquireLease")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono acquireLease(String proposedID, int duration, - ModifiedAccessConditions modifiedAccessConditions) { - if (!(duration == -1 || (duration >= 15 && duration <= 60))) { - // Throwing is preferred to Mono.error because this will error out immediately instead of waiting until - // subscription. - throw new IllegalArgumentException("Duration must be -1 or between 15 and 60."); - } - - return postProcessResponse(this.azureBlobStorage.blobs().acquireLeaseWithRestResponseAsync( - null, null, null, duration, proposedID, null, - modifiedAccessConditions, Context.NONE)); - } - - /** - * Renews the blob's previously-acquired lease. For more information, see the Azure Docs. - * - * @param leaseID - * The leaseId of the active lease on the blob. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blob_lease "Sample code for BlobAsyncRawClient.renewLease")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono renewLease(String leaseID) { - return this.renewLease(leaseID, null); - } - - /** - * Renews the blob's previously-acquired lease. For more information, see the Azure Docs. - * - * @param leaseID - * The leaseId of the active lease on the blob. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blob_lease "Sample code for BlobAsyncRawClient.renewLease")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono renewLease(String leaseID, ModifiedAccessConditions modifiedAccessConditions) { - return postProcessResponse(this.azureBlobStorage.blobs().renewLeaseWithRestResponseAsync(null, - null, leaseID, null, null, modifiedAccessConditions, Context.NONE)); - } - - /** - * Releases the blob's previously-acquired lease. For more information, see the Azure Docs. - * - * @param leaseID - * The leaseId of the active lease on the blob. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blob_lease "Sample code for BlobAsyncRawClient.releaseLease")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono releaseLease(String leaseID) { - return this.releaseLease(leaseID, null); - } - - /** - * Releases the blob's previously-acquired lease. For more information, see the Azure Docs. - * - * @param leaseID - * The leaseId of the active lease on the blob. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blob_lease "Sample code for BlobAsyncRawClient.releaseLease")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono releaseLease(String leaseID, - ModifiedAccessConditions modifiedAccessConditions) { - return postProcessResponse(this.azureBlobStorage.blobs().releaseLeaseWithRestResponseAsync(null, - null, leaseID, null, null, modifiedAccessConditions, Context.NONE)); - } - - /** - * BreakLease breaks the blob's previously-acquired lease (if it exists). Pass the LeaseBreakDefault (-1) constant - * to break a fixed-duration lease when it expires or an infinite lease immediately. For more information, see the - * Azure Docs. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blob_lease "Sample code for BlobAsyncRawClient.breakLease")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/New-Storage-SDK-V10-Preview/src/test/java/com/microsoft/azure/storage/Samples.java) - * - * @return - * Emits the successful response. - */ - public Mono breakLease() { - return this.breakLease(null, null); - } - - /** - * BreakLease breaks the blob's previously-acquired lease (if it exists). Pass the LeaseBreakDefault (-1) constant - * to break a fixed-duration lease when it expires or an infinite lease immediately. For more information, see the - * Azure Docs. - * - * @param breakPeriodInSeconds - * An optional {@code Integer} representing the proposed duration of seconds that the lease should continue - * before it is broken, between 0 and 60 seconds. This break period is only used if it is shorter than the - * time remaining on the lease. If longer, the time remaining on the lease is used. A new lease will not be - * available before the break period has expired, but the lease may be held for longer than the break - * period. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blob_lease "Sample code for BlobAsyncRawClient.breakLease")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono breakLease(Integer breakPeriodInSeconds, - ModifiedAccessConditions modifiedAccessConditions) { - return postProcessResponse(this.azureBlobStorage.blobs().breakLeaseWithRestResponseAsync(null, - null, null, breakPeriodInSeconds, null, modifiedAccessConditions, Context.NONE)); - } - - /** - * ChangeLease changes the blob's lease ID. For more information, see the Azure Docs. - * - * @param leaseId - * The leaseId of the active lease on the blob. - * @param proposedID - * A {@code String} in any valid GUID format. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blob_lease "Sample code for BlobAsyncRawClient.changeLease")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono changeLease(String leaseId, String proposedID) { - return this.changeLease(leaseId, proposedID, null); - } - - /** - * ChangeLease changes the blob's lease ID. For more information, see the Azure Docs. - * - * @param leaseId - * The leaseId of the active lease on the blob. - * @param proposedID - * A {@code String} in any valid GUID format. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blob_lease "Sample code for BlobAsyncRawClient.changeLease")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono changeLease(String leaseId, String proposedID, - ModifiedAccessConditions modifiedAccessConditions) { - return postProcessResponse(this.azureBlobStorage.blobs().changeLeaseWithRestResponseAsync(null, - null, leaseId, proposedID, null, null, modifiedAccessConditions, Context.NONE)); - } - - /** - * Returns the sku name and account kind for the account. For more information, please see the Azure Docs. - * - * @return Emits the successful response. - * - * @apiNote ## Sample code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=account_info "Sample code for BlobAsyncRawClient.getAccountInfo")] \n - * For more samples, please see the [Samples file](https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono getAccountInfo() { - return postProcessResponse( - this.azureBlobStorage.blobs().getAccountInfoWithRestResponseAsync(null, null, Context.NONE)); - } -} diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobClient.java index 21a2212713f5c..a937b8ca47613 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobClient.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobClient.java @@ -27,30 +27,30 @@ import java.time.OffsetDateTime; /** - * Client to a blob of any type: block, append, or page. It may only be instantiated through a {@link BlobClientBuilder} or via - * the method {@link ContainerClient#getBlobClient(String)}. This class does not hold any state about a particular - * blob, but is instead a convenient way of sending appropriate requests to the resource on the service. + * Client to a blob of any type: block, append, or page. It may only be instantiated through a {@link BlobClientBuilder} + * or via the method {@link ContainerClient#getBlobClient(String)}. This class does not hold any state about a + * particular blob, but is instead a convenient way of sending appropriate requests to the resource on the service. * *

* This client offers the ability to download blobs. Note that uploading data is specific to each type of blob. Please * refer to the {@link BlockBlobClient}, {@link PageBlobClient}, or {@link AppendBlobClient} for upload options. This - * client can be converted into one of these clients easily through the methods {@link #asBlockBlobClient}, {@link #asPageBlobClient}, - * and {@link #asAppendBlobClient}. + * client can be converted into one of these clients easily through the methods {@link #asBlockBlobClient}, {@link + * #asPageBlobClient}, and {@link #asAppendBlobClient}. * *

- * This client contains operations on a blob. Operations on a container are available on {@link ContainerClient}, - * and operations on the service are available on {@link StorageClient}. + * This client contains operations on a blob. Operations on a container are available on {@link ContainerClient}, and + * operations on the service are available on {@link StorageClient}. * *

- * Please refer to the Azure Docs - * for more information. + * Please refer to the Azure + * Docs for more information. */ public class BlobClient { - private static final int BLOB_DEFAULT_DOWNLOAD_BLOCK_SIZE = 4 * Constants.MB; private final BlobAsyncClient blobAsyncClient; /** * Package-private constructor for use by {@link BlobClientBuilder}. + * * @param blobAsyncClient the async blob client */ BlobClient(BlobAsyncClient blobAsyncClient) { @@ -58,45 +58,41 @@ public class BlobClient { } /** - * Creates a new {@link BlockBlobClient} to this resource, maintaining configurations. Only do this for blobs - * that are known to be block blobs. + * Creates a new {@link BlockBlobClient} to this resource, maintaining configurations. Only do this for blobs that + * are known to be block blobs. * - * @return - * A {@link BlockBlobClient} to this resource. + * @return A {@link BlockBlobClient} to this resource. */ public BlockBlobClient asBlockBlobClient() { return new BlockBlobClient(blobAsyncClient.asBlockBlobAsyncClient()); } /** - * Creates a new {@link AppendBlobClient} to this resource, maintaining configurations. Only do this for blobs - * that are known to be append blobs. + * Creates a new {@link AppendBlobClient} to this resource, maintaining configurations. Only do this for blobs that + * are known to be append blobs. * - * @return - * A {@link AppendBlobClient} to this resource. + * @return A {@link AppendBlobClient} to this resource. */ public AppendBlobClient asAppendBlobClient() { return new AppendBlobClient(blobAsyncClient.asAppendBlobAsyncClient()); } /** - * Creates a new {@link PageBlobClient} to this resource, maintaining configurations. Only do this for blobs - * that are known to be page blobs. + * Creates a new {@link PageBlobClient} to this resource, maintaining configurations. Only do this for blobs that + * are known to be page blobs. * - * @return - * A {@link PageBlobClient} to this resource. + * @return A {@link PageBlobClient} to this resource. */ public PageBlobClient asPageBlobClient() { return new PageBlobClient(blobAsyncClient.asPageBlobAsyncClient()); } /** - * Initializes a {@link ContainerClient} object pointing to the container this blob is in. This method does - * not create a container. It simply constructs the URL to the container and offers access to methods relevant to + * Initializes a {@link ContainerClient} object pointing to the container this blob is in. This method does not + * create a container. It simply constructs the URL to the container and offers access to methods relevant to * containers. * - * @return - * A {@link ContainerClient} object pointing to the container containing the blob + * @return A {@link ContainerClient} object pointing to the container containing the blob */ public ContainerClient getContainerClient() { return new ContainerClient(blobAsyncClient.getContainerAsyncClient()); @@ -104,6 +100,7 @@ public ContainerClient getContainerClient() { /** * Gets the URL of the blob represented by this client. + * * @return the URL. */ public URL getBlobUrl() { @@ -115,9 +112,7 @@ public URL getBlobUrl() { *

* * @return An InputStream object that represents the stream to use for reading from the blob. - * - * @throws StorageException - * If a storage service error occurred. + * @throws StorageException If a storage service error occurred. */ public final BlobInputStream openInputStream() { return openInputStream(new BlobRange(0), null); @@ -127,15 +122,11 @@ public final BlobInputStream openInputStream() { * Opens a blob input stream to download the specified range of the blob. *

* - * @param range - * {@link BlobRange} - * @param accessConditions - * An {@link BlobAccessConditions} object that represents the access conditions for the blob. - * + * @param range {@link BlobRange} + * @param accessConditions An {@link BlobAccessConditions} object that represents the access conditions for the + * blob. * @return An InputStream object that represents the stream to use for reading from the blob. - * - * @throws StorageException - * If a storage service error occurred. + * @throws StorageException If a storage service error occurred. */ public final BlobInputStream openInputStream(BlobRange range, BlobAccessConditions accessConditions) { return new BlobInputStream(blobAsyncClient, range.offset(), range.count(), accessConditions); @@ -153,10 +144,8 @@ public Response exists() { /** * Gets if the container this client represents exists in the cloud. * - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. - * @return - * true if the container exists, false if it doesn't + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @return true if the container exists, false if it doesn't */ public Response exists(Duration timeout) { Mono> response = blobAsyncClient.exists(); @@ -168,11 +157,8 @@ public Response exists(Duration timeout) { * Copies the data at the source URL to a blob. For more information, see the * Azure Docs * - * @param sourceURL - * The source URL to copy from. URLs outside of Azure may only be copied to block blobs. - * - * @return - * The copy ID for the long running operation. + * @param sourceURL The source URL to copy from. URLs outside of Azure may only be copied to block blobs. + * @return The copy ID for the long running operation. */ public Response startCopyFromURL(URL sourceURL) { return this.startCopyFromURL(sourceURL, null, null, null, null); @@ -182,26 +168,19 @@ public Response startCopyFromURL(URL sourceURL) { * Copies the data at the source URL to a blob. For more information, see the * Azure Docs * - * @param sourceURL - * The source URL to copy from. URLs outside of Azure may only be copied to block blobs. - * @param metadata - * {@link Metadata} - * @param sourceModifiedAccessConditions - * {@link ModifiedAccessConditions} against the source. Standard HTTP Access conditions related to the - * modification of data. ETag and LastModifiedTime are used to construct conditions related to when the blob - * was changed relative to the given request. The request will fail if the specified condition is not - * satisfied. - * @param destAccessConditions - * {@link BlobAccessConditions} against the destination. - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. - * - * @return - * The copy ID for the long running operation. + * @param sourceURL The source URL to copy from. URLs outside of Azure may only be copied to block blobs. + * @param metadata {@link Metadata} + * @param sourceModifiedAccessConditions {@link ModifiedAccessConditions} against the source. Standard HTTP Access + * conditions related to the modification of data. ETag and LastModifiedTime are used to construct conditions + * related to when the blob was changed relative to the given request. The request will fail if the specified + * condition is not satisfied. + * @param destAccessConditions {@link BlobAccessConditions} against the destination. + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @return The copy ID for the long running operation. */ public Response startCopyFromURL(URL sourceURL, Metadata metadata, - ModifiedAccessConditions sourceModifiedAccessConditions, BlobAccessConditions destAccessConditions, - Duration timeout) { + ModifiedAccessConditions sourceModifiedAccessConditions, BlobAccessConditions destAccessConditions, + Duration timeout) { Mono> response = blobAsyncClient .startCopyFromURL(sourceURL, metadata, sourceModifiedAccessConditions, destAccessConditions); @@ -211,9 +190,8 @@ public Response startCopyFromURL(URL sourceURL, Metadata metadata, /** * Stops a pending copy that was previously started and leaves a destination blob with 0 length and metadata. * - * @param copyId - * The id of the copy operation to abort. Returned as the {@code copyId} field on the {@link - * BlobStartCopyFromURLHeaders} object. + * @param copyId The id of the copy operation to abort. Returned as the {@code copyId} field on the {@link + * BlobStartCopyFromURLHeaders} object. * @return A response containing status code and HTTP headers. */ public VoidResponse abortCopyFromURL(String copyId) { @@ -223,14 +201,11 @@ public VoidResponse abortCopyFromURL(String copyId) { /** * Stops a pending copy that was previously started and leaves a destination blob with 0 length and metadata. * - * @param copyId - * The id of the copy operation to abort. Returned as the {@code copyId} field on the {@link - * BlobStartCopyFromURLHeaders} object. - * @param leaseAccessConditions - * By setting lease access conditions, requests will fail if the provided lease does not match the active - * lease on the blob. - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @param copyId The id of the copy operation to abort. Returned as the {@code copyId} field on the {@link + * BlobStartCopyFromURLHeaders} object. + * @param leaseAccessConditions By setting lease access conditions, requests will fail if the provided lease does + * not match the active lease on the blob. + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. * @return A response containing status code and HTTP headers. */ public VoidResponse abortCopyFromURL(String copyId, LeaseAccessConditions leaseAccessConditions, Duration timeout) { @@ -243,11 +218,8 @@ public VoidResponse abortCopyFromURL(String copyId, LeaseAccessConditions leaseA /** * Copies the data at the source URL to a blob and waits for the copy to complete before returning a response. * - * @param copySource - * The source URL to copy from. - * - * @return - * The copy ID for the long running operation. + * @param copySource The source URL to copy from. + * @return The copy ID for the long running operation. */ public Response copyFromURL(URL copySource) { return this.copyFromURL(copySource, null, null, null, null); @@ -256,26 +228,19 @@ public Response copyFromURL(URL copySource) { /** * Copies the data at the source URL to a blob and waits for the copy to complete before returning a response. * - * @param copySource - * The source URL to copy from. URLs outside of Azure may only be copied to block blobs. - * @param metadata - * {@link Metadata} - * @param sourceModifiedAccessConditions - * {@link ModifiedAccessConditions} against the source. Standard HTTP Access conditions related to the - * modification of data. ETag and LastModifiedTime are used to construct conditions related to when the blob - * was changed relative to the given request. The request will fail if the specified condition is not - * satisfied. - * @param destAccessConditions - * {@link BlobAccessConditions} against the destination. - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. - * - * @return - * The copy ID for the long running operation. + * @param copySource The source URL to copy from. URLs outside of Azure may only be copied to block blobs. + * @param metadata {@link Metadata} + * @param sourceModifiedAccessConditions {@link ModifiedAccessConditions} against the source. Standard HTTP Access + * conditions related to the modification of data. ETag and LastModifiedTime are used to construct conditions + * related to when the blob was changed relative to the given request. The request will fail if the specified + * condition is not satisfied. + * @param destAccessConditions {@link BlobAccessConditions} against the destination. + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @return The copy ID for the long running operation. */ public Response copyFromURL(URL copySource, Metadata metadata, - ModifiedAccessConditions sourceModifiedAccessConditions, BlobAccessConditions destAccessConditions, - Duration timeout) { + ModifiedAccessConditions sourceModifiedAccessConditions, BlobAccessConditions destAccessConditions, + Duration timeout) { Mono> response = blobAsyncClient .copyFromURL(copySource, metadata, sourceModifiedAccessConditions, destAccessConditions); @@ -286,8 +251,7 @@ public Response copyFromURL(URL copySource, Metadata metadata, * Downloads the entire blob into an output stream. Uploading data must be done from the {@link BlockBlobClient}, * {@link PageBlobClient}, or {@link AppendBlobClient}. * - * @param stream - * A non-null {@link OutputStream} instance where the downloaded data will be written. + * @param stream A non-null {@link OutputStream} instance where the downloaded data will be written. * @return A response containing status code and HTTP headers. * @throws UncheckedIOException If an I/O error occurs. */ @@ -296,23 +260,17 @@ public VoidResponse download(OutputStream stream) { } /** - * Downloads a range of bytes from a blob into an output stream. Uploading data must be done from the {@link BlockBlobClient}, - * {@link PageBlobClient}, or {@link AppendBlobClient}. + * Downloads a range of bytes from a blob into an output stream. Uploading data must be done from the {@link + * BlockBlobClient}, {@link PageBlobClient}, or {@link AppendBlobClient}. * - * @param stream - * A non-null {@link OutputStream} instance where the downloaded data will be written. + * @param stream A non-null {@link OutputStream} instance where the downloaded data will be written. * @param options {@link ReliableDownloadOptions} - * @param range - * {@link BlobRange} - * @param accessConditions - * {@link BlobAccessConditions} - * @param rangeGetContentMD5 - * Whether the contentMD5 for the specified blob range should be returned. - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @param range {@link BlobRange} + * @param accessConditions {@link BlobAccessConditions} + * @param rangeGetContentMD5 Whether the contentMD5 for the specified blob range should be returned. + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. * @return A response containing status code and HTTP headers. * @throws UncheckedIOException If an I/O error occurs. - * */ public VoidResponse download(OutputStream stream, ReliableDownloadOptions options, BlobRange range, BlobAccessConditions accessConditions, boolean rangeGetContentMD5, Duration timeout) { @@ -334,37 +292,32 @@ public VoidResponse download(OutputStream stream, ReliableDownloadOptions option /** * Downloads the entire blob into a file specified by the path. The file will be created if it doesn't exist. - * Uploading data must be done from the {@link BlockBlobClient}, {@link PageBlobClient}, or {@link AppendBlobClient}. + * Uploading data must be done from the {@link BlockBlobClient}, {@link PageBlobClient}, or {@link + * AppendBlobClient}. * - * @param filePath - * A non-null {@link OutputStream} instance where the downloaded data will be written. + * @param filePath A non-null {@link OutputStream} instance where the downloaded data will be written. * @throws IOException If an I/O error occurs */ public void downloadToFile(String filePath) throws IOException { - this.downloadToFile(filePath, null, null, BLOB_DEFAULT_DOWNLOAD_BLOCK_SIZE, null, false, null); + blobAsyncClient.downloadToFile(filePath); } /** * Downloads a range of bytes blob into a file specified by the path. The file will be created if it doesn't exist. - * Uploading data must be done from the {@link BlockBlobClient}, {@link PageBlobClient}, or {@link AppendBlobClient}. + * Uploading data must be done from the {@link BlockBlobClient}, {@link PageBlobClient}, or {@link + * AppendBlobClient}. * - * @param filePath - * A non-null {@link OutputStream} instance where the downloaded data will be written. + * @param filePath A non-null {@link OutputStream} instance where the downloaded data will be written. * @param options {@link ReliableDownloadOptions} - * @param range - * {@link BlobRange} - * @param blockSize - * the size of a chunk to download at a time, in bytes - * @param accessConditions - * {@link BlobAccessConditions} - * @param rangeGetContentMD5 - * Whether the contentMD5 for the specified blob range should be returned. - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @param range {@link BlobRange} + * @param blockSize the size of a chunk to download at a time, in bytes + * @param accessConditions {@link BlobAccessConditions} + * @param rangeGetContentMD5 Whether the contentMD5 for the specified blob range should be returned. + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. * @throws IOException If an I/O error occurs */ public void downloadToFile(String filePath, ReliableDownloadOptions options, BlobRange range, Integer blockSize, - BlobAccessConditions accessConditions, boolean rangeGetContentMD5, Duration timeout) throws IOException { + BlobAccessConditions accessConditions, boolean rangeGetContentMD5, Duration timeout) throws IOException { Mono download = blobAsyncClient.downloadToFile(filePath, range, blockSize, accessConditions, rangeGetContentMD5, options); try { @@ -386,19 +339,15 @@ public VoidResponse delete() { /** * Deletes the specified blob or snapshot. Note that deleting a blob also deletes all its snapshots. * - * @param deleteBlobSnapshotOptions - * Specifies the behavior for deleting the snapshots on this blob. {@code Include} will delete the base blob - * and all snapshots. {@code Only} will delete only the snapshots. If a snapshot is being deleted, you must - * pass null. - * @param accessConditions - * {@link BlobAccessConditions} - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. - * + * @param deleteBlobSnapshotOptions Specifies the behavior for deleting the snapshots on this blob. {@code Include} + * will delete the base blob and all snapshots. {@code Only} will delete only the snapshots. If a snapshot is being + * deleted, you must pass null. + * @param accessConditions {@link BlobAccessConditions} + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. * @return A response containing status code and HTTP headers. */ public VoidResponse delete(DeleteSnapshotsOptionType deleteBlobSnapshotOptions, - BlobAccessConditions accessConditions, Duration timeout) { + BlobAccessConditions accessConditions, Duration timeout) { Mono response = blobAsyncClient .delete(deleteBlobSnapshotOptions, accessConditions); @@ -408,8 +357,7 @@ public VoidResponse delete(DeleteSnapshotsOptionType deleteBlobSnapshotOptions, /** * Returns the blob's metadata and properties. * - * @return - * The blob properties and metadata. + * @return The blob properties and metadata. */ public Response getProperties() { return this.getProperties(null, null); @@ -418,13 +366,9 @@ public Response getProperties() { /** * Returns the blob's metadata and properties. * - * @param accessConditions - * {@link BlobAccessConditions} - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. - * - * @return - * The blob properties and metadata. + * @param accessConditions {@link BlobAccessConditions} + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @return The blob properties and metadata. */ public Response getProperties(BlobAccessConditions accessConditions, Duration timeout) { Mono> response = blobAsyncClient @@ -434,13 +378,12 @@ public Response getProperties(BlobAccessConditions accessConditi } /** - * Changes a blob's HTTP header properties. if only one HTTP header is updated, the - * others will all be erased. In order to preserve existing values, they must be - * passed alongside the header being changed. For more information, see the + * Changes a blob's HTTP header properties. if only one HTTP header is updated, the others will all be erased. In + * order to preserve existing values, they must be passed alongside the header being changed. For more information, + * see the * Azure Docs. * - * @param headers - * {@link BlobHTTPHeaders} + * @param headers {@link BlobHTTPHeaders} * @return A response containing status code and HTTP headers. */ public VoidResponse setHTTPHeaders(BlobHTTPHeaders headers) { @@ -448,21 +391,18 @@ public VoidResponse setHTTPHeaders(BlobHTTPHeaders headers) { } /** - * Changes a blob's HTTP header properties. if only one HTTP header is updated, the - * others will all be erased. In order to preserve existing values, they must be - * passed alongside the header being changed. For more information, see the + * Changes a blob's HTTP header properties. if only one HTTP header is updated, the others will all be erased. In + * order to preserve existing values, they must be passed alongside the header being changed. For more information, + * see the * Azure Docs. * - * @param headers - * {@link BlobHTTPHeaders} - * @param accessConditions - * {@link BlobAccessConditions} - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @param headers {@link BlobHTTPHeaders} + * @param accessConditions {@link BlobAccessConditions} + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. * @return A response containing status code and HTTP headers. */ public VoidResponse setHTTPHeaders(BlobHTTPHeaders headers, BlobAccessConditions accessConditions, - Duration timeout) { + Duration timeout) { Mono response = blobAsyncClient .setHTTPHeaders(headers, accessConditions); @@ -470,12 +410,11 @@ public VoidResponse setHTTPHeaders(BlobHTTPHeaders headers, BlobAccessConditions } /** - * Changes a blob's metadata. The specified metadata in this method will replace existing - * metadata. If old values must be preserved, they must be downloaded and included in the - * call to this method. For more information, see the Azure Docs. + * Changes a blob's metadata. The specified metadata in this method will replace existing metadata. If old values + * must be preserved, they must be downloaded and included in the call to this method. For more information, see the + * Azure Docs. * - * @param metadata - * {@link Metadata} + * @param metadata {@link Metadata} * @return A response containing status code and HTTP headers. */ public VoidResponse setMetadata(Metadata metadata) { @@ -483,16 +422,13 @@ public VoidResponse setMetadata(Metadata metadata) { } /** - * Changes a blob's metadata. The specified metadata in this method will replace existing - * metadata. If old values must be preserved, they must be downloaded and included in the - * call to this method. For more information, see the Azure Docs. + * Changes a blob's metadata. The specified metadata in this method will replace existing metadata. If old values + * must be preserved, they must be downloaded and included in the call to this method. For more information, see the + * Azure Docs. * - * @param metadata - * {@link Metadata} - * @param accessConditions - * {@link BlobAccessConditions} - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @param metadata {@link Metadata} + * @param accessConditions {@link BlobAccessConditions} + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. * @return A response containing status code and HTTP headers. */ public VoidResponse setMetadata(Metadata metadata, BlobAccessConditions accessConditions, Duration timeout) { @@ -505,8 +441,7 @@ public VoidResponse setMetadata(Metadata metadata, BlobAccessConditions accessCo /** * Creates a read-only snapshot of a blob. * - * @return - * The ID of the new snapshot. + * @return The ID of the new snapshot. */ public Response createSnapshot() { return this.createSnapshot(null, null, null); @@ -515,15 +450,10 @@ public Response createSnapshot() { /** * Creates a read-only snapshot of a blob. * - * @param metadata - * {@link Metadata} - * @param accessConditions - * {@link BlobAccessConditions} - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. - * - * @return - * The ID of the new snapshot. + * @param metadata {@link Metadata} + * @param accessConditions {@link BlobAccessConditions} + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @return The ID of the new snapshot. */ public Response createSnapshot(Metadata metadata, BlobAccessConditions accessConditions, Duration timeout) { Mono> response = blobAsyncClient @@ -535,10 +465,10 @@ public Response createSnapshot(Metadata metadata, BlobAccessConditions a /** * Sets the tier on a blob. The operation is allowed on a page blob in a premium storage account or a block blob in * a blob storage or GPV2 account. A premium page blob's tier determines the allowed size, IOPS, and bandwidth of - * the blob. A block blob's tier determines the Hot/Cool/Archive storage type. This does not update the blob's etag. + * the blob. A block blob's tier determines the Hot/Cool/Archive storage type. This does not update the blob's + * etag. * - * @param tier - * The new tier for the blob. + * @param tier The new tier for the blob. * @return A response containing status code and HTTP headers. */ public VoidResponse setTier(AccessTier tier) { @@ -548,15 +478,13 @@ public VoidResponse setTier(AccessTier tier) { /** * Sets the tier on a blob. The operation is allowed on a page blob in a premium storage account or a block blob in * a blob storage or GPV2 account. A premium page blob's tier determines the allowed size, IOPS, and bandwidth of - * the blob. A block blob's tier determines the Hot/Cool/Archive storage type. This does not update the blob's etag. - * - * @param tier - * The new tier for the blob. - * @param leaseAccessConditions - * By setting lease access conditions, requests will fail if the provided lease does not match the active - * lease on the blob. - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. + * the blob. A block blob's tier determines the Hot/Cool/Archive storage type. This does not update the blob's + * etag. + * + * @param tier The new tier for the blob. + * @param leaseAccessConditions By setting lease access conditions, requests will fail if the provided lease does + * not match the active lease on the blob. + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. * @return A response containing status code and HTTP headers. */ public VoidResponse setTier(AccessTier tier, LeaseAccessConditions leaseAccessConditions, Duration timeout) { @@ -578,8 +506,7 @@ public VoidResponse undelete() { /** * Undelete restores the content and metadata of a soft-deleted blob and/or any associated soft-deleted snapshots. * - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. * @return A response containing status code and HTTP headers. */ public VoidResponse undelete(Duration timeout) { @@ -593,14 +520,10 @@ public VoidResponse undelete(Duration timeout) { * Acquires a lease on the blob for write and delete operations. The lease duration must be between 15 to 60 * seconds, or infinite (-1). * - * @param proposedId - * A {@code String} in any valid GUID format. May be null. - * @param duration - * The duration of the lease, in seconds, or negative one (-1) for a lease that - * never expires. A non-infinite lease can be between 15 and 60 seconds. - * - * @return - * The lease ID. + * @param proposedId A {@code String} in any valid GUID format. May be null. + * @param duration The duration of the lease, in seconds, or negative one (-1) for a lease that never expires. A + * non-infinite lease can be between 15 and 60 seconds. + * @return The lease ID. */ public Response acquireLease(String proposedId, int duration) { return this.acquireLease(proposedId, duration, null, null); @@ -610,23 +533,17 @@ public Response acquireLease(String proposedId, int duration) { * Acquires a lease on the blob for write and delete operations. The lease duration must be between 15 to 60 * seconds, or infinite (-1). * - * @param proposedID - * A {@code String} in any valid GUID format. May be null. - * @param duration - * The duration of the lease, in seconds, or negative one (-1) for a lease that - * never expires. A non-infinite lease can be between 15 and 60 seconds. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. - * - * @return - * The lease ID. + * @param proposedID A {@code String} in any valid GUID format. May be null. + * @param duration The duration of the lease, in seconds, or negative one (-1) for a lease that never expires. A + * non-infinite lease can be between 15 and 60 seconds. + * @param modifiedAccessConditions Standard HTTP Access conditions related to the modification of data. ETag and + * LastModifiedTime are used to construct conditions related to when the blob was changed relative to the given + * request. The request will fail if the specified condition is not satisfied. + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @return The lease ID. */ public Response acquireLease(String proposedID, int duration, - ModifiedAccessConditions modifiedAccessConditions, Duration timeout) { + ModifiedAccessConditions modifiedAccessConditions, Duration timeout) { Mono> response = blobAsyncClient .acquireLease(proposedID, duration, modifiedAccessConditions); @@ -636,11 +553,8 @@ public Response acquireLease(String proposedID, int duration, /** * Renews the blob's previously-acquired lease. * - * @param leaseID - * The leaseId of the active lease on the blob. - * - * @return - * The renewed lease ID. + * @param leaseID The leaseId of the active lease on the blob. + * @return The renewed lease ID. */ public Response renewLease(String leaseID) { return this.renewLease(leaseID, null, null); @@ -649,20 +563,15 @@ public Response renewLease(String leaseID) { /** * Renews the blob's previously-acquired lease. * - * @param leaseID - * The leaseId of the active lease on the blob. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. - * - * @return - * The renewed lease ID. + * @param leaseID The leaseId of the active lease on the blob. + * @param modifiedAccessConditions Standard HTTP Access conditions related to the modification of data. ETag and + * LastModifiedTime are used to construct conditions related to when the blob was changed relative to the given + * request. The request will fail if the specified condition is not satisfied. + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @return The renewed lease ID. */ public Response renewLease(String leaseID, ModifiedAccessConditions modifiedAccessConditions, - Duration timeout) { + Duration timeout) { Mono> response = blobAsyncClient .renewLease(leaseID, modifiedAccessConditions); @@ -672,8 +581,7 @@ public Response renewLease(String leaseID, ModifiedAccessConditions modi /** * Releases the blob's previously-acquired lease. * - * @param leaseID - * The leaseId of the active lease on the blob. + * @param leaseID The leaseId of the active lease on the blob. * @return A response containing status code and HTTP headers. */ public VoidResponse releaseLease(String leaseID) { @@ -683,18 +591,15 @@ public VoidResponse releaseLease(String leaseID) { /** * Releases the blob's previously-acquired lease. * - * @param leaseID - * The leaseId of the active lease on the blob. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @param leaseID The leaseId of the active lease on the blob. + * @param modifiedAccessConditions Standard HTTP Access conditions related to the modification of data. ETag and + * LastModifiedTime are used to construct conditions related to when the blob was changed relative to the given + * request. The request will fail if the specified condition is not satisfied. + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. * @return A response containing status code and HTTP headers. */ public VoidResponse releaseLease(String leaseID, - ModifiedAccessConditions modifiedAccessConditions, Duration timeout) { + ModifiedAccessConditions modifiedAccessConditions, Duration timeout) { Mono response = blobAsyncClient .releaseLease(leaseID, modifiedAccessConditions); @@ -705,8 +610,7 @@ public VoidResponse releaseLease(String leaseID, * BreakLease breaks the blob's previously-acquired lease (if it exists). Pass the LeaseBreakDefault (-1) constant * to break a fixed-duration lease when it expires or an infinite lease immediately. * - * @return - * The remaining time in the broken lease in seconds. + * @return The remaining time in the broken lease in seconds. */ public Response breakLease() { return this.breakLease(null, null, null); @@ -716,24 +620,19 @@ public Response breakLease() { * BreakLease breaks the blob's previously-acquired lease (if it exists). Pass the LeaseBreakDefault (-1) constant * to break a fixed-duration lease when it expires or an infinite lease immediately. * - * @param breakPeriodInSeconds - * An optional {@code Integer} representing the proposed duration of seconds that the lease should continue - * before it is broken, between 0 and 60 seconds. This break period is only used if it is shorter than the - * time remaining on the lease. If longer, the time remaining on the lease is used. A new lease will not be - * available before the break period has expired, but the lease may be held for longer than the break - * period. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. - * - * @return - * The remaining time in the broken lease in seconds. + * @param breakPeriodInSeconds An optional {@code Integer} representing the proposed duration of seconds that the + * lease should continue before it is broken, between 0 and 60 seconds. This break period is only used if it is + * shorter than the time remaining on the lease. If longer, the time remaining on the lease is used. A new lease + * will not be available before the break period has expired, but the lease may be held for longer than the break + * period. + * @param modifiedAccessConditions Standard HTTP Access conditions related to the modification of data. ETag and + * LastModifiedTime are used to construct conditions related to when the blob was changed relative to the given + * request. The request will fail if the specified condition is not satisfied. + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @return The remaining time in the broken lease in seconds. */ public Response breakLease(Integer breakPeriodInSeconds, - ModifiedAccessConditions modifiedAccessConditions, Duration timeout) { + ModifiedAccessConditions modifiedAccessConditions, Duration timeout) { Mono> response = blobAsyncClient .breakLease(breakPeriodInSeconds, modifiedAccessConditions); @@ -743,36 +642,28 @@ public Response breakLease(Integer breakPeriodInSeconds, /** * ChangeLease changes the blob's lease ID. * - * @param leaseId - * The leaseId of the active lease on the blob. - * @param proposedID - * A {@code String} in any valid GUID format. - * - * @return - * The new lease ID. + * @param leaseId The leaseId of the active lease on the blob. + * @param proposedID A {@code String} in any valid GUID format. + * @return The new lease ID. */ public Response changeLease(String leaseId, String proposedID) { return this.changeLease(leaseId, proposedID, null, null); } /** - * ChangeLease changes the blob's lease ID. For more information, see the Azure Docs. - * - * @param leaseId - * The leaseId of the active lease on the blob. - * @param proposedID - * A {@code String} in any valid GUID format. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. + * ChangeLease changes the blob's lease ID. For more information, see the Azure + * Docs. * + * @param leaseId The leaseId of the active lease on the blob. + * @param proposedID A {@code String} in any valid GUID format. + * @param modifiedAccessConditions Standard HTTP Access conditions related to the modification of data. ETag and + * LastModifiedTime are used to construct conditions related to when the blob was changed relative to the given + * request. The request will fail if the specified condition is not satisfied. + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. * @return The new lease ID. */ public Response changeLease(String leaseId, String proposedID, - ModifiedAccessConditions modifiedAccessConditions, Duration timeout) { + ModifiedAccessConditions modifiedAccessConditions, Duration timeout) { Mono> response = blobAsyncClient .changeLease(leaseId, proposedID, modifiedAccessConditions); @@ -780,7 +671,8 @@ public Response changeLease(String leaseId, String proposedID, } /** - * Returns the sku name and account kind for the account. For more information, please see the Azure Docs. + * Returns the sku name and account kind for the account. For more information, please see the Azure Docs. * * @return The sku name and account kind. */ @@ -789,11 +681,10 @@ public Response getAccountInfo() { } /** - * Returns the sku name and account kind for the account. For more information, please see the Azure Docs. - * - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. + * Returns the sku name and account kind for the account. For more information, please see the Azure Docs. * + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. * @return The sku name and account kind. */ public Response getAccountInfo(Duration timeout) { @@ -806,49 +697,33 @@ public Response getAccountInfo(Duration timeout) { /** * Generates a user delegation SAS token with the specified parameters * - * @param userDelegationKey - * The {@code UserDelegationKey} user delegation key for the SAS - * @param accountName - * The {@code String} account name for the SAS - * @param permissions - * The {@code ContainerSASPermissions} permission for the SAS - * @param expiryTime - * The {@code OffsetDateTime} expiry time for the SAS - * - * @return - * A string that represents the SAS token + * @param userDelegationKey The {@code UserDelegationKey} user delegation key for the SAS + * @param accountName The {@code String} account name for the SAS + * @param permissions The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS + * @return A string that represents the SAS token */ public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, String accountName, - BlobSASPermission permissions, OffsetDateTime expiryTime) { + BlobSASPermission permissions, OffsetDateTime expiryTime) { return this.blobAsyncClient.generateUserDelegationSAS(userDelegationKey, accountName, permissions, expiryTime); } /** * Generates a user delegation SAS token with the specified parameters * - * @param userDelegationKey - * The {@code UserDelegationKey} user delegation key for the SAS - * @param accountName - * The {@code String} account name for the SAS - * @param permissions - * The {@code ContainerSASPermissions} permission for the SAS - * @param expiryTime - * The {@code OffsetDateTime} expiry time for the SAS - * @param startTime - * An optional {@code OffsetDateTime} start time for the SAS - * @param version - * An optional {@code String} version for the SAS - * @param sasProtocol - * An optional {@code SASProtocol} protocol for the SAS - * @param ipRange - * An optional {@code IPRange} ip address range for the SAS - * - * @return - * A string that represents the SAS token + * @param userDelegationKey The {@code UserDelegationKey} user delegation key for the SAS + * @param accountName The {@code String} account name for the SAS + * @param permissions The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS + * @param startTime An optional {@code OffsetDateTime} start time for the SAS + * @param version An optional {@code String} version for the SAS + * @param sasProtocol An optional {@code SASProtocol} protocol for the SAS + * @param ipRange An optional {@code IPRange} ip address range for the SAS + * @return A string that represents the SAS token */ public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, String accountName, - BlobSASPermission permissions, OffsetDateTime expiryTime, OffsetDateTime startTime, String version, - SASProtocol sasProtocol, IPRange ipRange) { + BlobSASPermission permissions, OffsetDateTime expiryTime, OffsetDateTime startTime, String version, + SASProtocol sasProtocol, IPRange ipRange) { return this.blobAsyncClient.generateUserDelegationSAS(userDelegationKey, accountName, permissions, expiryTime, startTime, version, sasProtocol, ipRange); } @@ -856,40 +731,25 @@ public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, Str /** * Generates a user delegation SAS token with the specified parameters * - * @param userDelegationKey - * The {@code UserDelegationKey} user delegation key for the SAS - * @param accountName - * The {@code String} account name for the SAS - * @param permissions - * The {@code ContainerSASPermissions} permission for the SAS - * @param expiryTime - * The {@code OffsetDateTime} expiry time for the SAS - * @param startTime - * An optional {@code OffsetDateTime} start time for the SAS - * @param version - * An optional {@code String} version for the SAS - * @param sasProtocol - * An optional {@code SASProtocol} protocol for the SAS - * @param ipRange - * An optional {@code IPRange} ip address range for the SAS - * @param cacheControl - * An optional {@code String} cache-control header for the SAS. - * @param contentDisposition - * An optional {@code String} content-disposition header for the SAS. - * @param contentEncoding - * An optional {@code String} content-encoding header for the SAS. - * @param contentLanguage - * An optional {@code String} content-language header for the SAS. - * @param contentType - * An optional {@code String} content-type header for the SAS. - * - * @return - * A string that represents the SAS token + * @param userDelegationKey The {@code UserDelegationKey} user delegation key for the SAS + * @param accountName The {@code String} account name for the SAS + * @param permissions The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS + * @param startTime An optional {@code OffsetDateTime} start time for the SAS + * @param version An optional {@code String} version for the SAS + * @param sasProtocol An optional {@code SASProtocol} protocol for the SAS + * @param ipRange An optional {@code IPRange} ip address range for the SAS + * @param cacheControl An optional {@code String} cache-control header for the SAS. + * @param contentDisposition An optional {@code String} content-disposition header for the SAS. + * @param contentEncoding An optional {@code String} content-encoding header for the SAS. + * @param contentLanguage An optional {@code String} content-language header for the SAS. + * @param contentType An optional {@code String} content-type header for the SAS. + * @return A string that represents the SAS token */ public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, String accountName, - BlobSASPermission permissions, OffsetDateTime expiryTime, OffsetDateTime startTime, String version, - SASProtocol sasProtocol, IPRange ipRange, String cacheControl, String contentDisposition, - String contentEncoding, String contentLanguage, String contentType) { + BlobSASPermission permissions, OffsetDateTime expiryTime, OffsetDateTime startTime, String version, + SASProtocol sasProtocol, IPRange ipRange, String cacheControl, String contentDisposition, + String contentEncoding, String contentLanguage, String contentType) { return this.blobAsyncClient.generateUserDelegationSAS(userDelegationKey, accountName, permissions, expiryTime, startTime, version, sasProtocol, ipRange, cacheControl, contentDisposition, contentEncoding, contentLanguage, contentType); @@ -898,13 +758,9 @@ public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, Str /** * Generates a SAS token with the specified parameters * - * @param expiryTime - * The {@code OffsetDateTime} expiry time for the SAS - * @param permissions - * The {@code ContainerSASPermissions} permission for the SAS - * - * @return - * A string that represents the SAS token + * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS + * @param permissions The {@code ContainerSASPermissions} permission for the SAS + * @return A string that represents the SAS token */ public String generateSAS(OffsetDateTime expiryTime, BlobSASPermission permissions) { return this.blobAsyncClient.generateSAS(permissions, expiryTime); @@ -913,11 +769,8 @@ public String generateSAS(OffsetDateTime expiryTime, BlobSASPermission permissio /** * Generates a SAS token with the specified parameters * - * @param identifier - * The {@code String} name of the access policy on the container this SAS references if any - * - * @return - * A string that represents the SAS token + * @param identifier The {@code String} name of the access policy on the container this SAS references if any + * @return A string that represents the SAS token */ public String generateSAS(String identifier) { return this.blobAsyncClient.generateSAS(identifier); @@ -926,26 +779,17 @@ public String generateSAS(String identifier) { /** * Generates a SAS token with the specified parameters * - * @param identifier - * The {@code String} name of the access policy on the container this SAS references if any - * @param permissions - * The {@code ContainerSASPermissions} permission for the SAS - * @param expiryTime - * The {@code OffsetDateTime} expiry time for the SAS - * @param startTime - * An optional {@code OffsetDateTime} start time for the SAS - * @param version - * An optional {@code String} version for the SAS - * @param sasProtocol - * An optional {@code SASProtocol} protocol for the SAS - * @param ipRange - * An optional {@code IPRange} ip address range for the SAS - * - * @return - * A string that represents the SAS token + * @param identifier The {@code String} name of the access policy on the container this SAS references if any + * @param permissions The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS + * @param startTime An optional {@code OffsetDateTime} start time for the SAS + * @param version An optional {@code String} version for the SAS + * @param sasProtocol An optional {@code SASProtocol} protocol for the SAS + * @param ipRange An optional {@code IPRange} ip address range for the SAS + * @return A string that represents the SAS token */ public String generateSAS(String identifier, BlobSASPermission permissions, OffsetDateTime expiryTime, - OffsetDateTime startTime, String version, SASProtocol sasProtocol, IPRange ipRange) { + OffsetDateTime startTime, String version, SASProtocol sasProtocol, IPRange ipRange) { return this.blobAsyncClient.generateSAS(identifier, permissions, expiryTime, startTime, version, sasProtocol, ipRange); } @@ -953,37 +797,23 @@ public String generateSAS(String identifier, BlobSASPermission permissions, Offs /** * Generates a SAS token with the specified parameters * - * @param identifier - * The {@code String} name of the access policy on the container this SAS references if any - * @param permissions - * The {@code ContainerSASPermissions} permission for the SAS - * @param expiryTime - * The {@code OffsetDateTime} expiry time for the SAS - * @param startTime - * An optional {@code OffsetDateTime} start time for the SAS - * @param version - * An optional {@code String} version for the SAS - * @param sasProtocol - * An optional {@code SASProtocol} protocol for the SAS - * @param ipRange - * An optional {@code IPRange} ip address range for the SAS - * @param cacheControl - * An optional {@code String} cache-control header for the SAS. - * @param contentDisposition - * An optional {@code String} content-disposition header for the SAS. - * @param contentEncoding - * An optional {@code String} content-encoding header for the SAS. - * @param contentLanguage - * An optional {@code String} content-language header for the SAS. - * @param contentType - * An optional {@code String} content-type header for the SAS. - * - * @return - * A string that represents the SAS token + * @param identifier The {@code String} name of the access policy on the container this SAS references if any + * @param permissions The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS + * @param startTime An optional {@code OffsetDateTime} start time for the SAS + * @param version An optional {@code String} version for the SAS + * @param sasProtocol An optional {@code SASProtocol} protocol for the SAS + * @param ipRange An optional {@code IPRange} ip address range for the SAS + * @param cacheControl An optional {@code String} cache-control header for the SAS. + * @param contentDisposition An optional {@code String} content-disposition header for the SAS. + * @param contentEncoding An optional {@code String} content-encoding header for the SAS. + * @param contentLanguage An optional {@code String} content-language header for the SAS. + * @param contentType An optional {@code String} content-type header for the SAS. + * @return A string that represents the SAS token */ public String generateSAS(String identifier, BlobSASPermission permissions, OffsetDateTime expiryTime, - OffsetDateTime startTime, String version, SASProtocol sasProtocol, IPRange ipRange, String cacheControl, - String contentDisposition, String contentEncoding, String contentLanguage, String contentType) { + OffsetDateTime startTime, String version, SASProtocol sasProtocol, IPRange ipRange, String cacheControl, + String contentDisposition, String contentEncoding, String contentLanguage, String contentType) { return this.blobAsyncClient.generateSAS(identifier, permissions, expiryTime, startTime, version, sasProtocol, ipRange, cacheControl, contentDisposition, contentEncoding, contentLanguage, contentType); } @@ -991,8 +821,7 @@ public String generateSAS(String identifier, BlobSASPermission permissions, Offs /** * Gets the snapshotId for a blob resource * - * @return - * A string that represents the snapshotId of the snapshot blob + * @return A string that represents the snapshotId of the snapshot blob */ public String getSnapshotId() { return this.blobAsyncClient.getSnapshotId(); @@ -1001,8 +830,7 @@ public String getSnapshotId() { /** * Determines if a blob is a snapshot * - * @return - * A boolean that indicates if a blob is a snapshot + * @return A boolean that indicates if a blob is a snapshot */ public boolean isSnapshot() { return this.blobAsyncClient.isSnapshot(); diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobInputStream.java b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobInputStream.java index 2e093f50738f2..1a990e179688b 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobInputStream.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobInputStream.java @@ -189,7 +189,7 @@ public synchronized void close() throws IOException { */ private synchronized void dispatchRead(final int readLength) throws IOException { try { - this.currentBuffer = this.blobClient.blobAsyncRawClient.download(new BlobRange(this.currentAbsoluteReadPosition, (long) readLength), this.accessCondition, false) + this.currentBuffer = this.blobClient.download(new BlobRange(this.currentAbsoluteReadPosition, (long) readLength), this.accessCondition, false) .flatMap(res -> ByteBufFlux.fromInbound(res.body(null)).aggregate().asByteBuffer()) .block(); diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobOutputStream.java b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobOutputStream.java index 176fe06c321d1..c733a580f2500 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobOutputStream.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobOutputStream.java @@ -295,7 +295,7 @@ private Mono writePages(Flux pageData, long offset, long writeLen PageBlobAccessConditions pageBlobAccessConditions = accessCondition == null ? null : new PageBlobAccessConditions().leaseAccessConditions(accessCondition.leaseAccessConditions()).modifiedAccessConditions(accessCondition.modifiedAccessConditions()); - return blobRef.pageBlobAsyncRawClient.uploadPages(new PageRange().start(offset).end(offset + writeLength - 1), pageData, pageBlobAccessConditions) + return blobRef.uploadPages(new PageRange().start(offset).end(offset + writeLength - 1), pageData, pageBlobAccessConditions) .then() .onErrorResume(t -> t instanceof StorageException, e -> { this.lastError = new IOException(e); @@ -312,7 +312,7 @@ private Mono appendBlock(Flux blockData, long offset, long writeL this.appendPositionAccessConditions.appendPosition(offset); AppendBlobAccessConditions appendBlobAccessConditions = accessCondition == null ? null : new AppendBlobAccessConditions().leaseAccessConditions(accessCondition.leaseAccessConditions()).modifiedAccessConditions(accessCondition.modifiedAccessConditions()); - return blobRef.appendBlobAsyncRawClient.appendBlock(blockData, writeLength, appendBlobAccessConditions) + return blobRef.appendBlock(blockData, writeLength, appendBlobAccessConditions) .then() .onErrorResume(t -> t instanceof IOException || t instanceof StorageException, e -> { this.lastError = new IOException(e); diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobURLParts.java b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobURLParts.java index 473d998c446b2..1200e960f7501 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobURLParts.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobURLParts.java @@ -76,14 +76,14 @@ public BlobURLParts host(String host) { } /** - * The container name or {@code null} if a {@link StorageAsyncRawClient} was parsed. + * The container name or {@code null} if a {@link StorageAsyncClient} was parsed. */ public String containerName() { return containerName; } /** - * The container name or {@code null} if a {@link StorageAsyncRawClient} was parsed. + * The container name or {@code null} if a {@link StorageAsyncClient} was parsed. */ public BlobURLParts containerName(String containerName) { this.containerName = containerName; @@ -91,14 +91,14 @@ public BlobURLParts containerName(String containerName) { } /** - * The blob name or {@code null} if a {@link StorageAsyncRawClient} or {@link ContainerAsyncClient} was parsed. + * The blob name or {@code null} if a {@link StorageAsyncClient} or {@link ContainerAsyncClient} was parsed. */ public String blobName() { return blobName; } /** - * The blob name or {@code null} if a {@link StorageAsyncRawClient} or {@link ContainerAsyncClient} was parsed. + * The blob name or {@code null} if a {@link StorageAsyncClient} or {@link ContainerAsyncClient} was parsed. */ public BlobURLParts blobName(String blobName) { this.blobName = blobName; diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobAsyncClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobAsyncClient.java index ada7a125d4ef1..e7d8aa9b0c03d 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobAsyncClient.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobAsyncClient.java @@ -8,6 +8,7 @@ import com.azure.core.http.rest.SimpleResponse; import com.azure.core.http.rest.VoidResponse; import com.azure.core.implementation.util.FluxUtil; +import com.azure.core.util.Context; import com.azure.storage.blob.implementation.AzureBlobStorageBuilder; import com.azure.storage.blob.models.BlobAccessConditions; import com.azure.storage.blob.models.BlobHTTPHeaders; @@ -15,11 +16,11 @@ import com.azure.storage.blob.models.BlockBlobItem; import com.azure.storage.blob.models.BlockItem; import com.azure.storage.blob.models.BlockListType; +import com.azure.storage.blob.models.BlockLookupList; import com.azure.storage.blob.models.LeaseAccessConditions; import com.azure.storage.blob.models.Metadata; import com.azure.storage.blob.models.SourceModifiedAccessConditions; import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -27,7 +28,6 @@ import java.io.IOException; import java.io.UncheckedIOException; import java.net.URL; -import java.nio.ByteBuffer; import java.nio.channels.AsynchronousFileChannel; import java.nio.charset.StandardCharsets; import java.nio.file.Paths; @@ -39,6 +39,8 @@ import java.util.TreeMap; import java.util.UUID; +import static com.azure.storage.blob.Utility.postProcessResponse; + /** * Client to a block blob. It may only be instantiated through a {@link BlockBlobClientBuilder}, via * the method {@link BlobAsyncClient#asBlockBlobAsyncClient()}, or via the method @@ -66,8 +68,6 @@ public final class BlockBlobAsyncClient extends BlobAsyncClient { static final int BLOB_DEFAULT_UPLOAD_BLOCK_SIZE = 4 * Constants.MB; static final int BLOB_MAX_UPLOAD_BLOCK_SIZE = 100 * Constants.MB; - final BlockBlobAsyncRawClient blockBlobAsyncRawClient; - /** * Indicates the maximum number of bytes that can be sent in a call to upload. */ @@ -89,7 +89,6 @@ public final class BlockBlobAsyncClient extends BlobAsyncClient { */ BlockBlobAsyncClient(AzureBlobStorageBuilder azureBlobStorageBuilder, String snapshot) { super(azureBlobStorageBuilder, snapshot); - this.blockBlobAsyncRawClient = new BlockBlobAsyncRawClient(azureBlobStorageBuilder.build(), snapshot); } /** @@ -114,7 +113,7 @@ public final class BlockBlobAsyncClient extends BlobAsyncClient { * @return * A reactive response containing the information of the uploaded block blob. */ - public Mono> upload(Flux data, long length) { + public Mono> upload(Flux data, long length) { return this.upload(data, length, null, null, null); } @@ -146,10 +145,15 @@ public Mono> upload(Flux data, long length) * @return * A reactive response containing the information of the uploaded block blob. */ - public Mono> upload(Flux data, long length, BlobHTTPHeaders headers, + public Mono> upload(Flux data, long length, BlobHTTPHeaders headers, Metadata metadata, BlobAccessConditions accessConditions) { - return blockBlobAsyncRawClient - .upload(data.map(Unpooled::wrappedBuffer), length, headers, metadata, accessConditions) + metadata = metadata == null ? new Metadata() : metadata; + accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions; + + return postProcessResponse(this.azureBlobStorage.blockBlobs().uploadWithRestResponseAsync(null, + null, data, length, null, metadata, null, null, + null, null, headers, accessConditions.leaseAccessConditions(), + accessConditions.modifiedAccessConditions(), Context.NONE)) .map(rb -> new SimpleResponse<>(rb, new BlockBlobItem(rb.deserializedHeaders()))); } @@ -291,8 +295,9 @@ public Mono stageBlock(String base64BlockID, Flux data, */ public Mono stageBlock(String base64BlockID, Flux data, long length, LeaseAccessConditions leaseAccessConditions) { - return blockBlobAsyncRawClient - .stageBlock(base64BlockID, data, length, leaseAccessConditions) + return postProcessResponse(this.azureBlobStorage.blockBlobs().stageBlockWithRestResponseAsync(null, + null, base64BlockID, length, data, null, null, null, + null, null, null, leaseAccessConditions, Context.NONE)) .map(VoidResponse::new); } @@ -349,8 +354,13 @@ public Mono stageBlockFromURL(String base64BlockID, URL sourceURL, public Mono stageBlockFromURL(String base64BlockID, URL sourceURL, BlobRange sourceRange, byte[] sourceContentMD5, LeaseAccessConditions leaseAccessConditions, SourceModifiedAccessConditions sourceModifiedAccessConditions) { - return blockBlobAsyncRawClient - .stageBlockFromURL(base64BlockID, sourceURL, sourceRange, sourceContentMD5, leaseAccessConditions, sourceModifiedAccessConditions) + sourceRange = sourceRange == null ? new BlobRange(0) : sourceRange; + + return postProcessResponse( + this.azureBlobStorage.blockBlobs().stageBlockFromURLWithRestResponseAsync(null, null, + base64BlockID, 0, sourceURL, sourceRange.toHeaderValue(), sourceContentMD5, null, + null, null, null, null, + leaseAccessConditions, sourceModifiedAccessConditions, Context.NONE)) .map(VoidResponse::new); } @@ -386,8 +396,9 @@ public Flux listBlocks(BlockListType listType) { */ public Flux listBlocks(BlockListType listType, LeaseAccessConditions leaseAccessConditions) { - return blockBlobAsyncRawClient - .listBlocks(listType, leaseAccessConditions) + return postProcessResponse(this.azureBlobStorage.blockBlobs().getBlockListWithRestResponseAsync( + null, null, listType, snapshot, null, null, null, + leaseAccessConditions, Context.NONE)) .map(ResponseBase::value) .flatMapMany(bl -> { Flux committed = Flux.fromIterable(bl.committedBlocks()) @@ -440,8 +451,13 @@ public Mono> commitBlockList(List base64BlockIDs */ public Mono> commitBlockList(List base64BlockIDs, BlobHTTPHeaders headers, Metadata metadata, BlobAccessConditions accessConditions) { - return blockBlobAsyncRawClient - .commitBlockList(base64BlockIDs, headers, metadata, accessConditions) + metadata = metadata == null ? new Metadata() : metadata; + accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions; + + return postProcessResponse(this.azureBlobStorage.blockBlobs().commitBlockListWithRestResponseAsync( + null, null, new BlockLookupList().latest(base64BlockIDs), null, metadata, + null, null, null, null, headers, + accessConditions.leaseAccessConditions(), accessConditions.modifiedAccessConditions(), Context.NONE)) .map(rb -> new SimpleResponse<>(rb, new BlockBlobItem(rb.deserializedHeaders()))); } } diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobAsyncRawClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobAsyncRawClient.java deleted file mode 100644 index 03b7e650167b6..0000000000000 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobAsyncRawClient.java +++ /dev/null @@ -1,364 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.azure.storage.blob; - -import com.azure.core.util.Context; -import com.azure.storage.blob.implementation.AzureBlobStorageImpl; -import com.azure.storage.blob.models.BlobAccessConditions; -import com.azure.storage.blob.models.BlobHTTPHeaders; -import com.azure.storage.blob.models.BlobRange; -import com.azure.storage.blob.models.BlockBlobsCommitBlockListResponse; -import com.azure.storage.blob.models.BlockBlobsGetBlockListResponse; -import com.azure.storage.blob.models.BlockBlobsStageBlockFromURLResponse; -import com.azure.storage.blob.models.BlockBlobsStageBlockResponse; -import com.azure.storage.blob.models.BlockBlobsUploadResponse; -import com.azure.storage.blob.models.BlockListType; -import com.azure.storage.blob.models.BlockLookupList; -import com.azure.storage.blob.models.LeaseAccessConditions; -import com.azure.storage.blob.models.Metadata; -import com.azure.storage.blob.models.SourceModifiedAccessConditions; -import io.netty.buffer.ByteBuf; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import java.net.URL; -import java.util.List; - -import static com.azure.storage.blob.Utility.postProcessResponse; - -/** - * Represents a URL to a block blob. It may be obtained by direct construction or via the create method on a - * {@link ContainerAsyncClient} object. This class does not hold any state about a particular blob but is instead a convenient - * way of sending off appropriate requests to the resource on the service. Please refer to the - * Azure Docs - * for more information on block blobs. - */ -final class BlockBlobAsyncRawClient extends BlobAsyncRawClient { - - /** - * Indicates the maximum number of bytes that can be sent in a call to upload. - */ - public static final int MAX_UPLOAD_BLOB_BYTES = 256 * Constants.MB; - - /** - * Indicates the maximum number of bytes that can be sent in a call to stageBlock. - */ - public static final int MAX_STAGE_BLOCK_BYTES = 100 * Constants.MB; - - /** - * Indicates the maximum number of blocks allowed in a block blob. - */ - public static final int MAX_BLOCKS = 50000; - - /** - * Creates a {@code BlockBlobAsyncRawClient} object pointing to the account specified by the URL and using the provided - */ - BlockBlobAsyncRawClient(AzureBlobStorageImpl azureBlobStorage, String snapshot) { - super(azureBlobStorage, snapshot); - } - - - /** - * Creates a new block blob, or updates the content of an existing block blob. - * Updating an existing block blob overwrites any existing metadata on the blob. Partial updates are not - * supported with PutBlob; the content of the existing blob is overwritten with the new content. To - * perform a partial update of a block blob's, use PutBlock and PutBlockList. - * For more information, see the - * Azure Docs. - *

- * Note that the data passed must be replayable if retries are enabled (the default). In other words, the - * {@code Flux} must produce the same data each time it is subscribed to. - *

- * - * @param data - * The data to write to the blob. Note that this {@code Flux} must be replayable if retries are enabled - * (the default). In other words, the Flowable must produce the same data each time it is subscribed to. - * @param length - * The exact length of the data. It is important that this value match precisely the length of the data - * emitted by the {@code Flux}. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=upload_download "Sample code for BlockBlobAsyncRawClient.upload")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono upload(Flux data, long length) { - return this.upload(data, length, null, null, null); - } - - /** - * Creates a new block blob, or updates the content of an existing block blob. - * Updating an existing block blob overwrites any existing metadata on the blob. Partial updates are not - * supported with PutBlob; the content of the existing blob is overwritten with the new content. To - * perform a partial update of a block blob's, use PutBlock and PutBlockList. - * For more information, see the - * Azure Docs. - *

- * Note that the data passed must be replayable if retries are enabled (the default). In other words, the - * {@code Flux} must produce the same data each time it is subscribed to. - *

- * - * @param data - * The data to write to the blob. Note that this {@code Flux} must be replayable if retries are enabled - * (the default). In other words, the Flowable must produce the same data each time it is subscribed to. - * @param length - * The exact length of the data. It is important that this value match precisely the length of the data - * emitted by the {@code Flux}. - * @param headers - * {@link BlobHTTPHeaders} - * @param metadata - * {@link Metadata} - * @param accessConditions - * {@link BlobAccessConditions} - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=upload_download "Sample code for BlockBlobAsyncRawClient.upload")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono upload(Flux data, long length, BlobHTTPHeaders headers, - Metadata metadata, BlobAccessConditions accessConditions) { - metadata = metadata == null ? new Metadata() : metadata; - accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions; - - return postProcessResponse(this.azureBlobStorage.blockBlobs().uploadWithRestResponseAsync(null, - null, data, length, null, metadata, null, null, - null, null, headers, accessConditions.leaseAccessConditions(), - accessConditions.modifiedAccessConditions(), Context.NONE)); - } - - /** - * Uploads the specified block to the block blob's "staging area" to be later committed by a call to - * commitBlockList. For more information, see the - * Azure Docs. - *

- * Note that the data passed must be replayable if retries are enabled (the default). In other words, the - * {@code Flux} must produce the same data each time it is subscribed to. - * - * @param base64BlockID - * A Base64 encoded {@code String} that specifies the ID for this block. Note that all block ids for a given - * blob must be the same length. - * @param data - * The data to write to the block. Note that this {@code Flux} must be replayable if retries are enabled - * (the default). In other words, the Flowable must produce the same data each time it is subscribed to. - * @param length - * The exact length of the data. It is important that this value match precisely the length of the data - * emitted by the {@code Flux}. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blocks "Sample code for BlockBlobAsyncRawClient.stageBlock")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono stageBlock(String base64BlockID, Flux data, - long length) { - return this.stageBlock(base64BlockID, data, length, null); - } - - /** - * Uploads the specified block to the block blob's "staging area" to be later committed by a call to - * commitBlockList. For more information, see the - * Azure Docs. - *

- * Note that the data passed must be replayable if retries are enabled (the default). In other words, the - * {@code Flux} must produce the same data each time it is subscribed to. - * - * @param base64BlockID - * A Base64 encoded {@code String} that specifies the ID for this block. Note that all block ids for a given - * blob must be the same length. - * @param data - * The data to write to the block. Note that this {@code Flux} must be replayable if retries are enabled - * (the default). In other words, the Flowable must produce the same data each time it is subscribed to. - * @param length - * The exact length of the data. It is important that this value match precisely the length of the data - * emitted by the {@code Flux}. - * @param leaseAccessConditions - * By setting lease access conditions, requests will fail if the provided lease does not match the active - * lease on the blob. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blocks "Sample code for BlockBlobAsyncRawClient.stageBlock")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono stageBlock(String base64BlockID, Flux data, long length, - LeaseAccessConditions leaseAccessConditions) { - return postProcessResponse(this.azureBlobStorage.blockBlobs().stageBlockWithRestResponseAsync(null, - null, base64BlockID, length, data, null, null, null, - null, null, null, leaseAccessConditions, Context.NONE)); - } - - /** - * Creates a new block to be committed as part of a blob where the contents are read from a URL. For more - * information, see the Azure Docs. - * - * @param base64BlockID - * A Base64 encoded {@code String} that specifies the ID for this block. Note that all block ids for a given - * blob must be the same length. - * @param sourceURL - * The url to the blob that will be the source of the copy. A source blob in the same storage account can be - * authenticated via Shared Key. However, if the source is a blob in another account, the source blob must - * either be public or must be authenticated via a shared access signature. If the source blob is public, no - * authentication is required to perform the operation. - * @param sourceRange - * {@link BlobRange} - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=block_from_url "Sample code for BlockBlobAsyncRawClient.stageBlockFromURL")] - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono stageBlockFromURL(String base64BlockID, URL sourceURL, - BlobRange sourceRange) { - return this.stageBlockFromURL(base64BlockID, sourceURL, sourceRange, null, - null, null); - } - - /** - * Creates a new block to be committed as part of a blob where the contents are read from a URL. For more - * information, see the Azure Docs. - * - * @param base64BlockID - * A Base64 encoded {@code String} that specifies the ID for this block. Note that all block ids for a given - * blob must be the same length. - * @param sourceURL - * The url to the blob that will be the source of the copy. A source blob in the same storage account can - * be authenticated via Shared Key. However, if the source is a blob in another account, the source blob - * must either be public or must be authenticated via a shared access signature. If the source blob is - * public, no authentication is required to perform the operation. - * @param sourceRange - * {@link BlobRange} - * @param sourceContentMD5 - * An MD5 hash of the block content from the source blob. If specified, the service will calculate the MD5 - * of the received data and fail the request if it does not match the provided MD5. - * @param leaseAccessConditions - * By setting lease access conditions, requests will fail if the provided lease does not match the active - * lease on the blob. - * @param sourceModifiedAccessConditions - * {@link SourceModifiedAccessConditions} - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=block_from_url "Sample code for BlockBlobAsyncRawClient.stageBlockFromURL")] - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono stageBlockFromURL(String base64BlockID, URL sourceURL, - BlobRange sourceRange, byte[] sourceContentMD5, LeaseAccessConditions leaseAccessConditions, - SourceModifiedAccessConditions sourceModifiedAccessConditions) { - sourceRange = sourceRange == null ? new BlobRange(0) : sourceRange; - - return postProcessResponse( - this.azureBlobStorage.blockBlobs().stageBlockFromURLWithRestResponseAsync(null, null, - base64BlockID, 0, sourceURL, sourceRange.toHeaderValue(), sourceContentMD5, null, - null, null, null, null, - leaseAccessConditions, sourceModifiedAccessConditions, Context.NONE)); - } - - /** - * Returns the list of blocks that have been uploaded as part of a block blob using the specified block list filter. - * For more information, see the - * Azure Docs. - * - * @param listType - * Specifies which type of blocks to return. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blocks "Sample code for BlockBlobAsyncRawClient.listBlocks")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono listBlocks(BlockListType listType) { - return this.listBlocks(listType, null); - } - - /** - * Returns the list of blocks that have been uploaded as part of a block blob using the specified block list filter. - * For more information, see the - * Azure Docs. - * - * @param listType - * Specifies which type of blocks to return. - * @param leaseAccessConditions - * By setting lease access conditions, requests will fail if the provided lease does not match the active - * lease on the blob. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blocks "Sample code for BlockBlobAsyncRawClient.listBlocks")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono listBlocks(BlockListType listType, - LeaseAccessConditions leaseAccessConditions) { - return postProcessResponse(this.azureBlobStorage.blockBlobs().getBlockListWithRestResponseAsync( - null, null, listType, snapshot, null, null, null, - leaseAccessConditions, Context.NONE)); - } - - /** - * Writes a blob by specifying the list of block IDs that are to make up the blob. - * In order to be written as part of a blob, a block must have been successfully written - * to the server in a prior stageBlock operation. You can call commitBlockList to update a blob - * by uploading only those blocks that have changed, then committing the new and existing - * blocks together. Any blocks not specified in the block list and permanently deleted. - * For more information, see the - * Azure Docs. - *

- * - * @param base64BlockIDs - * A list of base64 encode {@code String}s that specifies the block IDs to be committed. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blocks "Sample code for BlockBlobAsyncRawClient.commitBlockList")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono commitBlockList(List base64BlockIDs) { - return this.commitBlockList(base64BlockIDs, null, null, null); - } - - /** - * Writes a blob by specifying the list of block IDs that are to make up the blob. - * In order to be written as part of a blob, a block must have been successfully written - * to the server in a prior stageBlock operation. You can call commitBlockList to update a blob - * by uploading only those blocks that have changed, then committing the new and existing - * blocks together. Any blocks not specified in the block list and permanently deleted. - * For more information, see the - * Azure Docs. - *

- * - * @param base64BlockIDs - * A list of base64 encode {@code String}s that specifies the block IDs to be committed. - * @param headers - * {@link BlobHTTPHeaders} - * @param metadata - * {@link Metadata} - * @param accessConditions - * {@link BlobAccessConditions} - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=blocks "Sample code for BlockBlobAsyncRawClient.commitBlockList")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono commitBlockList(List base64BlockIDs, - BlobHTTPHeaders headers, Metadata metadata, BlobAccessConditions accessConditions) { - metadata = metadata == null ? new Metadata() : metadata; - accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions; - - return postProcessResponse(this.azureBlobStorage.blockBlobs().commitBlockListWithRestResponseAsync( - null, null, new BlockLookupList().latest(base64BlockIDs), null, metadata, - null, null, null, null, headers, - accessConditions.leaseAccessConditions(), accessConditions.modifiedAccessConditions(), Context.NONE)); - } -} diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobClient.java index 9dced1f87022b..ec76f684c1bb4 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobClient.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobClient.java @@ -4,7 +4,6 @@ package com.azure.storage.blob; import com.azure.core.http.rest.Response; -import com.azure.core.http.rest.SimpleResponse; import com.azure.core.http.rest.VoidResponse; import com.azure.storage.blob.models.BlobAccessConditions; import com.azure.storage.blob.models.BlobHTTPHeaders; @@ -44,22 +43,22 @@ * for more information. */ public final class BlockBlobClient extends BlobClient { + private final BlockBlobAsyncClient blockBlobAsyncClient; - private BlockBlobAsyncClient blockBlobAsyncClient; /** * Indicates the maximum number of bytes that can be sent in a call to upload. */ - public static final int MAX_UPLOAD_BLOB_BYTES = 256 * Constants.MB; + public static final int MAX_UPLOAD_BLOB_BYTES = BlockBlobAsyncClient.MAX_UPLOAD_BLOB_BYTES; /** * Indicates the maximum number of bytes that can be sent in a call to stageBlock. */ - public static final int MAX_STAGE_BLOCK_BYTES = 100 * Constants.MB; + public static final int MAX_STAGE_BLOCK_BYTES = BlockBlobAsyncClient.MAX_STAGE_BLOCK_BYTES; /** * Indicates the maximum number of blocks allowed in a block blob. */ - public static final int MAX_BLOCKS = 50000; + public static final int MAX_BLOCKS = BlockBlobAsyncClient.MAX_BLOCKS; /** * Package-private constructor for use by {@link BlockBlobClientBuilder}. @@ -161,9 +160,8 @@ public Response upload(InputStream data, long length, BlobHTTPHea return ByteBufAllocator.DEFAULT.buffer((int) count).writeBytes(cache); })); - Mono> upload = blockBlobAsyncClient.blockBlobAsyncRawClient - .upload(fbb.subscribeOn(Schedulers.elastic()), length, headers, metadata, accessConditions) - .map(rb -> new SimpleResponse<>(rb, new BlockBlobItem(rb.deserializedHeaders()))); + Mono> upload = blockBlobAsyncClient + .upload(fbb.subscribeOn(Schedulers.elastic()), length, headers, metadata, accessConditions); try { return Utility.blockWithOptionalTimeout(upload, timeout); diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerAsyncClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerAsyncClient.java index f979f084ac151..6d9e64f16a924 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerAsyncClient.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerAsyncClient.java @@ -9,6 +9,7 @@ import com.azure.core.http.rest.VoidResponse; import com.azure.core.util.Context; import com.azure.storage.blob.implementation.AzureBlobStorageBuilder; +import com.azure.storage.blob.implementation.AzureBlobStorageImpl; import com.azure.storage.blob.models.BlobFlatListSegment; import com.azure.storage.blob.models.BlobHierarchyListSegment; import com.azure.storage.blob.models.BlobItem; @@ -33,57 +34,59 @@ import java.net.URL; import java.time.Duration; import java.time.OffsetDateTime; +import java.time.temporal.ChronoUnit; import java.util.List; +import static com.azure.storage.blob.Utility.postProcessResponse; + /** - * Client to a container. It may only be instantiated through a {@link ContainerClientBuilder} or via the method - * {@link StorageAsyncClient#getContainerAsyncClient(String)}. This class does not hold any - * state about a particular blob but is instead a convenient way of sending off appropriate requests to - * the resource on the service. It may also be used to construct URLs to blobs. + * Client to a container. It may only be instantiated through a {@link ContainerClientBuilder} or via the method {@link + * StorageAsyncClient#getContainerAsyncClient(String)}. This class does not hold any state about a particular blob but + * is instead a convenient way of sending off appropriate requests to the resource on the service. It may also be used + * to construct URLs to blobs. * *

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

- * Please refer to the Azure Docs - * for more information on containers. + * Please refer to the Azure + * Docs for more information on containers. * *

- * Note this client is an async client that returns reactive responses from Spring Reactor Core - * project (https://projectreactor.io/). Calling the methods in this client will NOT - * start the actual network operation, until {@code .subscribe()} is called on the reactive response. - * You can simply convert one of these responses to a {@link java.util.concurrent.CompletableFuture} - * object through {@link Mono#toFuture()}. + * Note this client is an async client that returns reactive responses from Spring Reactor Core project + * (https://projectreactor.io/). Calling the methods in this client will NOT start the actual network + * operation, until {@code .subscribe()} is called on the reactive response. You can simply convert one of these + * responses to a {@link java.util.concurrent.CompletableFuture} object through {@link Mono#toFuture()}. */ public final class ContainerAsyncClient { - ContainerAsyncRawClient containerAsyncRawClient; - public static final String ROOT_CONTAINER_NAME = "$root"; public static final String STATIC_WEBSITE_CONTAINER_NAME = "$web"; public static final String LOG_CONTAINER_NAME = "$logs"; + private final AzureBlobStorageImpl azureBlobStorage; + /** * Package-private constructor for use by {@link ContainerClientBuilder}. + * * @param azureBlobStorageBuilder the API client builder for blob storage API */ ContainerAsyncClient(AzureBlobStorageBuilder azureBlobStorageBuilder) { - this.containerAsyncRawClient = new ContainerAsyncRawClient(azureBlobStorageBuilder.build()); + this.azureBlobStorage = azureBlobStorageBuilder.build(); } /** * Creates a new {@link BlockBlobAsyncClient} object by concatenating the blobName to the end of - * ContainerAsyncClient's URL. The new BlockBlobAsyncClient uses the same request policy pipeline as the ContainerAsyncClient. - * To change the pipeline, create the BlockBlobAsyncClient and then call its WithPipeline method passing in the - * desired pipeline object. Or, call this package's NewBlockBlobAsyncClient instead of calling this object's - * NewBlockBlobAsyncClient method. - * - * @param blobName - * A {@code String} representing the name of the blob. - * - * @return A new {@link BlockBlobAsyncClient} object which references the blob with the specified name in this container. + * ContainerAsyncClient's URL. The new BlockBlobAsyncClient uses the same request policy pipeline as the + * ContainerAsyncClient. To change the pipeline, create the BlockBlobAsyncClient and then call its WithPipeline + * method passing in the desired pipeline object. Or, call this package's NewBlockBlobAsyncClient instead of calling + * this object's NewBlockBlobAsyncClient method. + * + * @param blobName A {@code String} representing the name of the blob. + * @return A new {@link BlockBlobAsyncClient} object which references the blob with the specified name in this + * container. */ public BlockBlobAsyncClient getBlockBlobAsyncClient(String blobName) { return getBlockBlobAsyncClient(blobName, null); @@ -91,106 +94,95 @@ public BlockBlobAsyncClient getBlockBlobAsyncClient(String blobName) { /** * Creates a new {@link BlockBlobAsyncClient} object by concatenating the blobName to the end of - * ContainerAsyncClient's URL. The new BlockBlobAsyncClient uses the same request policy pipeline as the ContainerAsyncClient. - * To change the pipeline, create the BlockBlobAsyncClient and then call its WithPipeline method passing in the - * desired pipeline object. Or, call this package's NewBlockBlobAsyncClient instead of calling this object's - * NewBlockBlobAsyncClient method. - * - * @param blobName - * A {@code String} representing the name of the blob. - * @param snapshot - * the snapshot identifier for the blob. - * - * @return A new {@link BlockBlobAsyncClient} object which references the blob with the specified name in this container. + * ContainerAsyncClient's URL. The new BlockBlobAsyncClient uses the same request policy pipeline as the + * ContainerAsyncClient. To change the pipeline, create the BlockBlobAsyncClient and then call its WithPipeline + * method passing in the desired pipeline object. Or, call this package's NewBlockBlobAsyncClient instead of calling + * this object's NewBlockBlobAsyncClient method. + * + * @param blobName A {@code String} representing the name of the blob. + * @param snapshot the snapshot identifier for the blob. + * @return A new {@link BlockBlobAsyncClient} object which references the blob with the specified name in this + * container. */ public BlockBlobAsyncClient getBlockBlobAsyncClient(String blobName, String snapshot) { return new BlockBlobAsyncClient(new AzureBlobStorageBuilder() .url(Utility.appendToURLPath(getContainerUrl(), blobName).toString()) - .pipeline(containerAsyncRawClient.azureBlobStorage.httpPipeline()), snapshot); + .pipeline(azureBlobStorage.httpPipeline()), snapshot); } /** - * Creates creates a new PageBlobAsyncClient object by concatenating blobName to the end of - * ContainerAsyncClient's URL. The new PageBlobAsyncClient uses the same request policy pipeline as the ContainerAsyncClient. - * To change the pipeline, create the PageBlobAsyncClient and then call its WithPipeline method passing in the - * desired pipeline object. Or, call this package's NewPageBlobAsyncClient instead of calling this object's - * NewPageBlobAsyncClient method. - * - * @param blobName - * A {@code String} representing the name of the blob. - * - * @return A new {@link PageBlobAsyncClient} object which references the blob with the specified name in this container. + * Creates creates a new PageBlobAsyncClient object by concatenating blobName to the end of ContainerAsyncClient's + * URL. The new PageBlobAsyncClient uses the same request policy pipeline as the ContainerAsyncClient. To change the + * pipeline, create the PageBlobAsyncClient and then call its WithPipeline method passing in the desired pipeline + * object. Or, call this package's NewPageBlobAsyncClient instead of calling this object's NewPageBlobAsyncClient + * method. + * + * @param blobName A {@code String} representing the name of the blob. + * @return A new {@link PageBlobAsyncClient} object which references the blob with the specified name in this + * container. */ public PageBlobAsyncClient getPageBlobAsyncClient(String blobName) { return getPageBlobAsyncClient(blobName, null); } /** - * Creates creates a new PageBlobAsyncClient object by concatenating blobName to the end of - * ContainerAsyncClient's URL. The new PageBlobAsyncClient uses the same request policy pipeline as the ContainerAsyncClient. - * To change the pipeline, create the PageBlobAsyncClient and then call its WithPipeline method passing in the - * desired pipeline object. Or, call this package's NewPageBlobAsyncClient instead of calling this object's - * NewPageBlobAsyncClient method. - * - * @param blobName - * A {@code String} representing the name of the blob. - * @param snapshot - * the snapshot identifier for the blob. - * - * @return A new {@link PageBlobAsyncClient} object which references the blob with the specified name in this container. + * Creates creates a new PageBlobAsyncClient object by concatenating blobName to the end of ContainerAsyncClient's + * URL. The new PageBlobAsyncClient uses the same request policy pipeline as the ContainerAsyncClient. To change the + * pipeline, create the PageBlobAsyncClient and then call its WithPipeline method passing in the desired pipeline + * object. Or, call this package's NewPageBlobAsyncClient instead of calling this object's NewPageBlobAsyncClient + * method. + * + * @param blobName A {@code String} representing the name of the blob. + * @param snapshot the snapshot identifier for the blob. + * @return A new {@link PageBlobAsyncClient} object which references the blob with the specified name in this + * container. */ public PageBlobAsyncClient getPageBlobAsyncClient(String blobName, String snapshot) { return new PageBlobAsyncClient(new AzureBlobStorageBuilder() .url(Utility.appendToURLPath(getContainerUrl(), blobName).toString()) - .pipeline(containerAsyncRawClient.azureBlobStorage.httpPipeline()), snapshot); + .pipeline(azureBlobStorage.httpPipeline()), snapshot); } /** - * Creates creates a new AppendBlobAsyncClient object by concatenating blobName to the end of - * ContainerAsyncClient's URL. The new AppendBlobAsyncClient uses the same request policy pipeline as the ContainerAsyncClient. - * To change the pipeline, create the AppendBlobAsyncClient and then call its WithPipeline method passing in the - * desired pipeline object. Or, call this package's NewAppendBlobAsyncClient instead of calling this object's + * Creates creates a new AppendBlobAsyncClient object by concatenating blobName to the end of ContainerAsyncClient's + * URL. The new AppendBlobAsyncClient uses the same request policy pipeline as the ContainerAsyncClient. To change + * the pipeline, create the AppendBlobAsyncClient and then call its WithPipeline method passing in the desired + * pipeline object. Or, call this package's NewAppendBlobAsyncClient instead of calling this object's * NewAppendBlobAsyncClient method. * - * @param blobName - * A {@code String} representing the name of the blob. - * - * @return A new {@link AppendBlobAsyncClient} object which references the blob with the specified name in this container. + * @param blobName A {@code String} representing the name of the blob. + * @return A new {@link AppendBlobAsyncClient} object which references the blob with the specified name in this + * container. */ public AppendBlobAsyncClient getAppendBlobAsyncClient(String blobName) { return getAppendBlobAsyncClient(blobName, null); } /** - * Creates creates a new AppendBlobAsyncClient object by concatenating blobName to the end of - * ContainerAsyncClient's URL. The new AppendBlobAsyncClient uses the same request policy pipeline as the ContainerAsyncClient. - * To change the pipeline, create the AppendBlobAsyncClient and then call its WithPipeline method passing in the - * desired pipeline object. Or, call this package's NewAppendBlobAsyncClient instead of calling this object's + * Creates creates a new AppendBlobAsyncClient object by concatenating blobName to the end of ContainerAsyncClient's + * URL. The new AppendBlobAsyncClient uses the same request policy pipeline as the ContainerAsyncClient. To change + * the pipeline, create the AppendBlobAsyncClient and then call its WithPipeline method passing in the desired + * pipeline object. Or, call this package's NewAppendBlobAsyncClient instead of calling this object's * NewAppendBlobAsyncClient method. * - * @param blobName - * A {@code String} representing the name of the blob. - * @param snapshot - * the snapshot identifier for the blob. - * - * @return A new {@link AppendBlobAsyncClient} object which references the blob with the specified name in this container. + * @param blobName A {@code String} representing the name of the blob. + * @param snapshot the snapshot identifier for the blob. + * @return A new {@link AppendBlobAsyncClient} object which references the blob with the specified name in this + * container. */ public AppendBlobAsyncClient getAppendBlobAsyncClient(String blobName, String snapshot) { return new AppendBlobAsyncClient(new AzureBlobStorageBuilder() .url(Utility.appendToURLPath(getContainerUrl(), blobName).toString()) - .pipeline(containerAsyncRawClient.azureBlobStorage.httpPipeline()), snapshot); + .pipeline(azureBlobStorage.httpPipeline()), snapshot); } /** - * Creates a new BlobAsyncClient object by concatenating blobName to the end of - * ContainerAsyncClient's URL. The new BlobAsyncClient uses the same request policy pipeline as the ContainerAsyncClient. - * To change the pipeline, create the BlobAsyncClient and then call its WithPipeline method passing in the - * desired pipeline object. Or, call this package's getBlobAsyncClient instead of calling this object's - * getBlobAsyncClient method. - * - * @param blobName - * A {@code String} representing the name of the blob. + * Creates a new BlobAsyncClient object by concatenating blobName to the end of ContainerAsyncClient's URL. The new + * BlobAsyncClient uses the same request policy pipeline as the ContainerAsyncClient. To change the pipeline, create + * the BlobAsyncClient and then call its WithPipeline method passing in the desired pipeline object. Or, call this + * package's getBlobAsyncClient instead of calling this object's getBlobAsyncClient method. * + * @param blobName A {@code String} representing the name of the blob. * @return A new {@link BlobAsyncClient} object which references the blob with the specified name in this container. */ public BlobAsyncClient getBlobAsyncClient(String blobName) { @@ -198,55 +190,50 @@ public BlobAsyncClient getBlobAsyncClient(String blobName) { } /** - * Creates a new BlobAsyncClient object by concatenating blobName to the end of - * ContainerAsyncClient's URL. The new BlobAsyncClient uses the same request policy pipeline as the ContainerAsyncClient. - * To change the pipeline, create the BlobAsyncClient and then call its WithPipeline method passing in the - * desired pipeline object. Or, call this package's getBlobAsyncClient instead of calling this object's - * getBlobAsyncClient method. - * - * @param blobName - * A {@code String} representing the name of the blob. - * @param snapshot - * the snapshot identifier for the blob. + * Creates a new BlobAsyncClient object by concatenating blobName to the end of ContainerAsyncClient's URL. The new + * BlobAsyncClient uses the same request policy pipeline as the ContainerAsyncClient. To change the pipeline, create + * the BlobAsyncClient and then call its WithPipeline method passing in the desired pipeline object. Or, call this + * package's getBlobAsyncClient instead of calling this object's getBlobAsyncClient method. * + * @param blobName A {@code String} representing the name of the blob. + * @param snapshot the snapshot identifier for the blob. * @return A new {@link BlobAsyncClient} object which references the blob with the specified name in this container. */ public BlobAsyncClient getBlobAsyncClient(String blobName, String snapshot) { return new BlobAsyncClient(new AzureBlobStorageBuilder() .url(Utility.appendToURLPath(getContainerUrl(), blobName).toString()) - .pipeline(containerAsyncRawClient.azureBlobStorage.httpPipeline()), snapshot); + .pipeline(azureBlobStorage.httpPipeline()), snapshot); } /** * Initializes a {@link StorageAsyncClient} object pointing to the storage account this container is in. * - * @return - * A {@link StorageAsyncClient} object pointing to the specified storage account + * @return A {@link StorageAsyncClient} object pointing to the specified storage account */ public StorageAsyncClient getStorageAsyncClient() { return new StorageAsyncClient(new AzureBlobStorageBuilder() .url(Utility.stripLastPathSegment(getContainerUrl()).toString()) - .pipeline(containerAsyncRawClient.azureBlobStorage.httpPipeline())); + .pipeline(azureBlobStorage.httpPipeline())); } /** * Gets the URL of the container represented by this client. + * * @return the URL. * @throws RuntimeException If the container has a malformed URL. */ public URL getContainerUrl() { try { - return new URL(containerAsyncRawClient.azureBlobStorage.url()); + return new URL(azureBlobStorage.url()); } catch (MalformedURLException e) { - throw new RuntimeException(String.format("Invalid URL on %s: %s" + getClass().getSimpleName(), containerAsyncRawClient.azureBlobStorage.url()), e); + throw new RuntimeException(String.format("Invalid URL on %s: %s" + getClass().getSimpleName(), azureBlobStorage.url()), e); } } /** * Gets if the container this client represents exists in the cloud. * - * @return - * true if the container exists, false if it doesn't + * @return true if the container exists, false if it doesn't */ public Mono> exists() { return this.getProperties(null) @@ -262,8 +249,7 @@ public Mono> exists() { * fails. For more information, see the * Azure Docs. * - * @return - * A reactive response signalling completion. + * @return A reactive response signalling completion. */ public Mono create() { return this.create(null, null); @@ -274,47 +260,52 @@ public Mono create() { * fails. For more information, see the * Azure Docs. * - * @param metadata - * {@link Metadata} - * @param accessType - * Specifies how the data in this container is available to the public. See the x-ms-blob-public-access header - * in the Azure Docs for more information. Pass null for no public access. - * - * @return - * A reactive response signalling completion. + * @param metadata {@link Metadata} + * @param accessType Specifies how the data in this container is available to the public. See the + * x-ms-blob-public-access header in the Azure Docs for more information. Pass null for no public access. + * @return A reactive response signalling completion. */ public Mono create(Metadata metadata, PublicAccessType accessType) { - return containerAsyncRawClient - .create(metadata, accessType) + metadata = metadata == null ? new Metadata() : metadata; + + return postProcessResponse(this.azureBlobStorage.containers().createWithRestResponseAsync( + null, null, metadata, accessType, null, Context.NONE)) .map(VoidResponse::new); } /** - * Marks the specified container for deletion. The container and any blobs contained within it are later - * deleted during garbage collection. For more information, see the + * Marks the specified container for deletion. The container and any blobs contained within it are later deleted + * during garbage collection. For more information, see the * Azure Docs. * - * @return - * A reactive response signalling completion. + * @return A reactive response signalling completion. */ public Mono delete() { return this.delete(null); } /** - * Marks the specified container for deletion. The container and any blobs contained within it are later - * deleted during garbage collection. For more information, see the + * Marks the specified container for deletion. The container and any blobs contained within it are later deleted + * during garbage collection. For more information, see the * Azure Docs. * - * @param accessConditions - * {@link ContainerAccessConditions} - * - * @return - * A reactive response signalling completion. + * @param accessConditions {@link ContainerAccessConditions} + * @return A reactive response signalling completion. + * @throws UnsupportedOperationException If {@link ContainerAccessConditions#modifiedAccessConditions()} has either + * {@link ModifiedAccessConditions#ifMatch()} or {@link ModifiedAccessConditions#ifNoneMatch()} set. */ public Mono delete(ContainerAccessConditions accessConditions) { - return containerAsyncRawClient - .delete(accessConditions) + accessConditions = accessConditions == null ? new ContainerAccessConditions() : accessConditions; + + if (!validateNoEtag(accessConditions.modifiedAccessConditions())) { + // Throwing is preferred to Single.error because this will error out immediately instead of waiting until + // subscription. + throw new UnsupportedOperationException("ETag access conditions are not supported for this API."); + } + + return postProcessResponse(this.azureBlobStorage.containers() + .deleteWithRestResponseAsync(null, null, null, + accessConditions.leaseAccessConditions(), accessConditions.modifiedAccessConditions(), Context.NONE)) .map(VoidResponse::new); } @@ -322,8 +313,7 @@ public Mono delete(ContainerAccessConditions accessConditions) { * Returns the container's metadata and system properties. For more information, see the * Azure Docs. * - * @return - * A reactive response containing the container properties. + * @return A reactive response containing the container properties. */ public Mono> getProperties() { return this.getProperties(null); @@ -333,16 +323,14 @@ public Mono> getProperties() { * Returns the container's metadata and system properties. For more information, see the * Azure Docs. * - * @param leaseAccessConditions - * By setting lease access conditions, requests will fail if the provided lease does not match the active - * lease on the blob. - * - * @return - * A reactive response containing the container properties. + * @param leaseAccessConditions By setting lease access conditions, requests will fail if the provided lease does + * not match the active lease on the blob. + * @return A reactive response containing the container properties. */ public Mono> getProperties(LeaseAccessConditions leaseAccessConditions) { - return containerAsyncRawClient - .getProperties(leaseAccessConditions) + return postProcessResponse(this.azureBlobStorage.containers() + .getPropertiesWithRestResponseAsync(null, null, null, + leaseAccessConditions, Context.NONE)) .map(rb -> new SimpleResponse<>(rb, new ContainerProperties(rb.deserializedHeaders()))); } @@ -350,11 +338,8 @@ public Mono> getProperties(LeaseAccessConditions l * Sets the container's metadata. For more information, see the * Azure Docs. * - * @param metadata - * {@link Metadata} - * - * @return - * A reactive response signalling completion. + * @param metadata {@link Metadata} + * @return A reactive response signalling completion. */ public Mono setMetadata(Metadata metadata) { return this.setMetadata(metadata, null); @@ -364,18 +349,27 @@ public Mono setMetadata(Metadata metadata) { * Sets the container's metadata. For more information, see the * Azure Docs. * - * @param metadata - * {@link Metadata} - * @param accessConditions - * {@link ContainerAccessConditions} - * - * @return - * A reactive response signalling completion. + * @param metadata {@link Metadata} + * @param accessConditions {@link ContainerAccessConditions} + * @return A reactive response signalling completion. + * @throws UnsupportedOperationException If {@link ContainerAccessConditions#modifiedAccessConditions()} has + * anything set other than {@link ModifiedAccessConditions#ifModifiedSince()}. */ public Mono setMetadata(Metadata metadata, - ContainerAccessConditions accessConditions) { - return containerAsyncRawClient - .setMetadata(metadata, accessConditions) + ContainerAccessConditions accessConditions) { + metadata = metadata == null ? new Metadata() : metadata; + accessConditions = accessConditions == null ? new ContainerAccessConditions() : accessConditions; + if (!validateNoEtag(accessConditions.modifiedAccessConditions()) + || accessConditions.modifiedAccessConditions().ifUnmodifiedSince() != null) { + // Throwing is preferred to Single.error because this will error out immediately instead of waiting until + // subscription. + throw new UnsupportedOperationException( + "If-Modified-Since is the only HTTP access condition supported for this API"); + } + + return postProcessResponse(this.azureBlobStorage.containers() + .setMetadataWithRestResponseAsync(null, null, metadata, null, + accessConditions.leaseAccessConditions(), accessConditions.modifiedAccessConditions(), Context.NONE)) .map(VoidResponse::new); } @@ -384,8 +378,7 @@ public Mono setMetadata(Metadata metadata, * For more information, see the * Azure Docs. * - * @return - * A reactive response containing the container access policy. + * @return A reactive response containing the container access policy. */ public Mono> getAccessPolicy() { return this.getAccessPolicy(null); @@ -396,15 +389,13 @@ public Mono> getAccessPolicy() { * For more information, see the * Azure Docs. * - * @param leaseAccessConditions - * By setting lease access conditions, requests will fail if the provided lease does not match the active - * lease on the blob. - * - * @return - * A reactive response containing the container access policy. + * @param leaseAccessConditions By setting lease access conditions, requests will fail if the provided lease does + * not match the active lease on the blob. + * @return A reactive response containing the container access policy. */ public Mono> getAccessPolicy(LeaseAccessConditions leaseAccessConditions) { - return containerAsyncRawClient.getAccessPolicy(leaseAccessConditions); + return postProcessResponse(this.azureBlobStorage.containers().getAccessPolicyWithRestResponseAsync(null, null, null, leaseAccessConditions, Context.NONE) + .map(response -> new SimpleResponse<>(response, new ContainerAccessPolicies(response.deserializedHeaders().blobPublicAccess(), response.value())))); } /** @@ -413,19 +404,16 @@ public Mono> getAccessPolicy(LeaseAccessCondit * ensure the time formatting is compatible with the service. For more information, see the * Azure Docs. * - * @param accessType - * Specifies how the data in this container is available to the public. See the x-ms-blob-public-access header - * in the Azure Docs for more information. Pass null for no public access. - * @param identifiers - * A list of {@link SignedIdentifier} objects that specify the permissions for the container. Please see - * here - * for more information. Passing null will clear all access policies. - * - * @return - * A reactive response signalling completion. + * @param accessType Specifies how the data in this container is available to the public. See the + * x-ms-blob-public-access header in the Azure Docs for more information. Pass null for no public access. + * @param identifiers A list of {@link SignedIdentifier} objects that specify the permissions for the container. + * Please see + * here + * for more information. Passing null will clear all access policies. + * @return A reactive response signalling completion. */ public Mono setAccessPolicy(PublicAccessType accessType, - List identifiers) { + List identifiers) { return this.setAccessPolicy(accessType, identifiers, null); } @@ -435,79 +423,129 @@ public Mono setAccessPolicy(PublicAccessType accessType, * ensure the time formatting is compatible with the service. For more information, see the * Azure Docs. * - * @param accessType - * Specifies how the data in this container is available to the public. See the x-ms-blob-public-access header - * in the Azure Docs for more information. Pass null for no public access. - * @param identifiers - * A list of {@link SignedIdentifier} objects that specify the permissions for the container. Please see - * here - * for more information. Passing null will clear all access policies. - * @param accessConditions - * {@link ContainerAccessConditions} - * - * @return - * A reactive response signalling completion. + * @param accessType Specifies how the data in this container is available to the public. See the + * x-ms-blob-public-access header in the Azure Docs for more information. Pass null for no public access. + * @param identifiers A list of {@link SignedIdentifier} objects that specify the permissions for the container. + * Please see + * here + * for more information. Passing null will clear all access policies. + * @param accessConditions {@link ContainerAccessConditions} + * @return A reactive response signalling completion. + * @throws UnsupportedOperationException If {@link ContainerAccessConditions#modifiedAccessConditions()} has either + * {@link ModifiedAccessConditions#ifMatch()} or {@link ModifiedAccessConditions#ifNoneMatch()} set. */ public Mono setAccessPolicy(PublicAccessType accessType, - List identifiers, ContainerAccessConditions accessConditions) { - return containerAsyncRawClient - .setAccessPolicy(accessType, identifiers, accessConditions) + List identifiers, ContainerAccessConditions accessConditions) { + accessConditions = accessConditions == null ? new ContainerAccessConditions() : accessConditions; + + if (!validateNoEtag(accessConditions.modifiedAccessConditions())) { + // Throwing is preferred to Single.error because this will error out immediately instead of waiting until + // subscription. + throw new UnsupportedOperationException("ETag access conditions are not supported for this API."); + } + + /* + We truncate to seconds because the service only supports nanoseconds or seconds, but doing an + OffsetDateTime.now will only give back milliseconds (more precise fields are zeroed and not serialized). This + allows for proper serialization with no real detriment to users as sub-second precision on active time for + signed identifiers is not really necessary. + */ + if (identifiers != null) { + for (SignedIdentifier identifier : identifiers) { + if (identifier.accessPolicy() != null && identifier.accessPolicy().start() != null) { + identifier.accessPolicy().start( + identifier.accessPolicy().start().truncatedTo(ChronoUnit.SECONDS)); + } + if (identifier.accessPolicy() != null && identifier.accessPolicy().expiry() != null) { + identifier.accessPolicy().expiry( + identifier.accessPolicy().expiry().truncatedTo(ChronoUnit.SECONDS)); + } + } + } + + return postProcessResponse(this.azureBlobStorage.containers() + .setAccessPolicyWithRestResponseAsync(null, identifiers, null, accessType, + null, accessConditions.leaseAccessConditions(), accessConditions.modifiedAccessConditions(), + Context.NONE)) .map(VoidResponse::new); } /** - * Returns a reactive Publisher emitting all the blobs in this container lazily as needed. - * The directories are flattened and only actual blobs and no directories are returned. + * Returns a reactive Publisher emitting all the blobs in this container lazily as needed. The directories are + * flattened and only actual blobs and no directories are returned. * *

* Blob names are returned in lexicographic order. For more information, see the * Azure Docs. * *

- * E.g. listing a container containing a 'foo' folder, which contains blobs 'foo1' and 'foo2', and a blob - * on the root level 'bar', will return + * E.g. listing a container containing a 'foo' folder, which contains blobs 'foo1' and 'foo2', and a blob on the + * root level 'bar', will return * *

    - *
  • foo/foo1 - *
  • foo/foo2 - *
  • bar + *
  • foo/foo1 + *
  • foo/foo2 + *
  • bar *
* - * @return - * A reactive response emitting the flattened blobs. + * @return A reactive response emitting the flattened blobs. */ public Flux listBlobsFlat() { return this.listBlobsFlat(new ListBlobsOptions()); } /** - * Returns a reactive Publisher emitting all the blobs in this container lazily as needed. - * The directories are flattened and only actual blobs and no directories are returned. + * Returns a reactive Publisher emitting all the blobs in this container lazily as needed. The directories are + * flattened and only actual blobs and no directories are returned. * *

* Blob names are returned in lexicographic order. For more information, see the * Azure Docs. * *

- * E.g. listing a container containing a 'foo' folder, which contains blobs 'foo1' and 'foo2', and a blob - * on the root level 'bar', will return + * E.g. listing a container containing a 'foo' folder, which contains blobs 'foo1' and 'foo2', and a blob on the + * root level 'bar', will return * *

    - *
  • foo/foo1 - *
  • foo/foo2 - *
  • bar + *
  • foo/foo1 + *
  • foo/foo2 + *
  • bar *
* + * @param options {@link ListBlobsOptions} + * @return A reactive response emitting the listed blobs, flattened. + */ + public Flux listBlobsFlat(ListBlobsOptions options) { + return listBlobsFlatSegment(null, options).flatMapMany(response -> listBlobsFlatHelper(options, response)); + } + + /* + * Returns a single segment of blobs starting from the specified Marker. Use an empty + * marker to start enumeration from the beginning. Blob names are returned in lexicographic order. + * After getting a segment, process it, and then call ListBlobs again (passing the the previously-returned + * Marker) to get the next segment. For more information, see the + * Azure Docs. + * + * @param marker + * Identifies the portion of the list to be returned with the next list operation. + * This value is returned in the response of a previous list operation as the + * ListBlobsFlatSegmentResponse.body().nextMarker(). Set to null to list the first segment. * @param options * {@link ListBlobsOptions} * - * @return - * A reactive response emitting the listed blobs, flattened. + * @return Emits the successful response. + * + * @apiNote ## Sample Code \n + * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=list_blobs_flat "Sample code for ContainerAsyncClient.listBlobsFlatSegment")] \n + * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=list_blobs_flat_helper "helper code for ContainerAsyncClient.listBlobsFlatSegment")] \n + * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) */ - public Flux listBlobsFlat(ListBlobsOptions options) { - return containerAsyncRawClient - .listBlobsFlatSegment(null, options) - .flatMapMany(response -> listBlobsFlatHelper(options, response)); + private Mono listBlobsFlatSegment(String marker, ListBlobsOptions options) { + options = options == null ? new ListBlobsOptions() : options; + + return postProcessResponse(this.azureBlobStorage.containers() + .listBlobFlatSegmentWithRestResponseAsync(null, options.prefix(), marker, + options.maxResults(), options.details().toList(), null, null, Context.NONE)); } private Flux listBlobsFlatHelper(ListBlobsOptions options, ContainersListBlobFlatSegmentResponse response) { @@ -521,7 +559,7 @@ private Flux listBlobsFlatHelper(ListBlobsOptions options, ContainersL if (response.value().nextMarker() != null) { // Recursively add the continuation items to the observable. - result = result.concatWith(containerAsyncRawClient.listBlobsFlatSegment(response.value().nextMarker(), options) + result = result.concatWith(listBlobsFlatSegment(response.value().nextMarker(), options) .flatMapMany(r -> listBlobsFlatHelper(options, r))); } @@ -529,80 +567,109 @@ private Flux listBlobsFlatHelper(ListBlobsOptions options, ContainersL } /** - * Returns a reactive Publisher emitting all the blobs and directories (prefixes) under - * the given directory (prefix). Directories will have {@link BlobItem#isPrefix()} set to - * true. + * Returns a reactive Publisher emitting all the blobs and directories (prefixes) under the given directory + * (prefix). Directories will have {@link BlobItem#isPrefix()} set to true. * *

* Blob names are returned in lexicographic order. For more information, see the * Azure Docs. * *

- * E.g. listing a container containing a 'foo' folder, which contains blobs 'foo1' and 'foo2', and a blob - * on the root level 'bar', will return the following results when prefix=null: + * E.g. listing a container containing a 'foo' folder, which contains blobs 'foo1' and 'foo2', and a blob on the + * root level 'bar', will return the following results when prefix=null: * *

    - *
  • foo/ (isPrefix = true) - *
  • bar (isPrefix = false) + *
  • foo/ (isPrefix = true) + *
  • bar (isPrefix = false) *
*

* will return the following results when prefix="foo/": * *

    - *
  • foo/foo1 (isPrefix = false) - *
  • foo/foo2 (isPrefix = false) + *
  • foo/foo1 (isPrefix = false) + *
  • foo/foo2 (isPrefix = false) *
* - * @param directory - * The directory to list blobs underneath - * - * @return - * A reactive response emitting the prefixes and blobs. + * @param directory The directory to list blobs underneath + * @return A reactive response emitting the prefixes and blobs. */ public Flux listBlobsHierarchy(String directory) { return this.listBlobsHierarchy("/", new ListBlobsOptions().prefix(directory)); } /** - * Returns a reactive Publisher emitting all the blobs and prefixes (directories) under - * the given prefix (directory). Directories will have {@link BlobItem#isPrefix()} set to - * true. + * Returns a reactive Publisher emitting all the blobs and prefixes (directories) under the given prefix + * (directory). Directories will have {@link BlobItem#isPrefix()} set to true. * *

* Blob names are returned in lexicographic order. For more information, see the * Azure Docs. * *

- * E.g. listing a container containing a 'foo' folder, which contains blobs 'foo1' and 'foo2', and a blob - * on the root level 'bar', will return the following results when prefix=null: + * E.g. listing a container containing a 'foo' folder, which contains blobs 'foo1' and 'foo2', and a blob on the + * root level 'bar', will return the following results when prefix=null: * *

    - *
  • foo/ (isPrefix = true) - *
  • bar (isPrefix = false) + *
  • foo/ (isPrefix = true) + *
  • bar (isPrefix = false) *
*

* will return the following results when prefix="foo/": * *

    - *
  • foo/foo1 (isPrefix = false) - *
  • foo/foo2 (isPrefix = false) + *
  • foo/foo1 (isPrefix = false) + *
  • foo/foo2 (isPrefix = false) *
* + * @param delimiter The delimiter for blob hierarchy, "/" for hierarchy based on directories + * @param options {@link ListBlobsOptions} + * @return A reactive response emitting the prefixes and blobs. + */ + public Flux listBlobsHierarchy(String delimiter, ListBlobsOptions options) { + return listBlobsHierarchySegment(null, delimiter, options) + .flatMapMany(response -> listBlobsHierarchyHelper(delimiter, options, Context.NONE, response)); + } + + /* + * Returns a single segment of blobs and blob prefixes starting from the specified Marker. Use an empty + * marker to start enumeration from the beginning. Blob names are returned in lexicographic order. + * After getting a segment, process it, and then call ListBlobs again (passing the the previously-returned + * Marker) to get the next segment. For more information, see the + * Azure Docs. + * + * @param marker + * Identifies the portion of the list to be returned with the next list operation. + * This value is returned in the response of a previous list operation as the + * ListBlobsHierarchySegmentResponse.body().nextMarker(). Set to null to list the first segment. * @param delimiter - * The delimiter for blob hierarchy, "/" for hierarchy based on directories + * The operation returns a BlobPrefix element in the response body that acts as a placeholder for all blobs + * whose names begin with the same substring up to the appearance of the delimiter character. The delimiter may + * be a single character or a string. * @param options * {@link ListBlobsOptions} * - * @return - * A reactive response emitting the prefixes and blobs. + * @return Emits the successful response. + * @throws UnsupportedOperationException If {@link ListBlobsOptions#details()} has {@link BlobListDetails#snapshots()} + * set. + * + * @apiNote ## Sample Code \n + * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=list_blobs_hierarchy "Sample code for ContainerAsyncClient.listBlobsHierarchySegment")] \n + * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=list_blobs_hierarchy_helper "helper code for ContainerAsyncClient.listBlobsHierarchySegment")] \n + * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) */ - public Flux listBlobsHierarchy(String delimiter, ListBlobsOptions options) { - return containerAsyncRawClient.listBlobsHierarchySegment(null, delimiter, options) - .flatMapMany(response -> listBlobsHierarchyHelper(delimiter, options, Context.NONE, response)); + private Mono listBlobsHierarchySegment(String marker, String delimiter, ListBlobsOptions options) { + options = options == null ? new ListBlobsOptions() : options; + if (options.details().snapshots()) { + throw new UnsupportedOperationException("Including snapshots in a hierarchical listing is not supported."); + } + + return postProcessResponse(this.azureBlobStorage.containers() + .listBlobHierarchySegmentWithRestResponseAsync(null, delimiter, options.prefix(), marker, + options.maxResults(), options.details().toList(), null, null, Context.NONE)); } private Flux listBlobsHierarchyHelper(String delimiter, ListBlobsOptions options, - Context context, ContainersListBlobHierarchySegmentResponse response) { + Context context, ContainersListBlobHierarchySegmentResponse response) { Flux blobs; Flux prefixes; BlobHierarchyListSegment segment = response.value().segment(); @@ -620,7 +687,7 @@ private Flux listBlobsHierarchyHelper(String delimiter, ListBlobsOptio if (response.value().nextMarker() != null) { // Recursively add the continuation items to the observable. - result = result.concatWith(containerAsyncRawClient.listBlobsHierarchySegment(response.value().nextMarker(), delimiter, options) + result = result.concatWith(listBlobsHierarchySegment(response.value().nextMarker(), delimiter, options) .flatMapMany(r -> listBlobsHierarchyHelper(delimiter, options, context, r))); } @@ -699,14 +766,10 @@ private Flux listBlobsHierarchyHelper(String delimiter, ListBlobsOptio * Acquires a lease on the blob for write and delete operations. The lease duration must be between 15 to 60 * seconds, or infinite (-1). * - * @param proposedId - * A {@code String} in any valid GUID format. May be null. - * @param duration - * The duration of the lease, in seconds, or negative one (-1) for a lease that - * never expires. A non-infinite lease can be between 15 and 60 seconds. - * - * @return - * A reactive response containing the lease ID. + * @param proposedId A {@code String} in any valid GUID format. May be null. + * @param duration The duration of the lease, in seconds, or negative one (-1) for a lease that never expires. A + * non-infinite lease can be between 15 and 60 seconds. + * @return A reactive response containing the lease ID. */ public Mono> acquireLease(String proposedId, int duration) { return this.acquireLease(proposedId, duration, null); @@ -716,33 +779,34 @@ public Mono> acquireLease(String proposedId, int duration) { * Acquires a lease on the blob for write and delete operations. The lease duration must be between 15 to 60 * seconds, or infinite (-1). * - * @param proposedID - * A {@code String} in any valid GUID format. May be null. - * @param duration - * The duration of the lease, in seconds, or negative one (-1) for a lease that - * never expires. A non-infinite lease can be between 15 and 60 seconds. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * - * @return - * A reactive response containing the lease ID. + * @param proposedID A {@code String} in any valid GUID format. May be null. + * @param duration The duration of the lease, in seconds, or negative one (-1) for a lease that never expires. A + * non-infinite lease can be between 15 and 60 seconds. + * @param modifiedAccessConditions Standard HTTP Access conditions related to the modification of data. ETag and + * LastModifiedTime are used to construct conditions related to when the blob was changed relative to the given + * request. The request will fail if the specified condition is not satisfied. + * @return A reactive response containing the lease ID. + * @throws UnsupportedOperationException If either {@link ModifiedAccessConditions#ifMatch()} or {@link + * ModifiedAccessConditions#ifNoneMatch()} is set. */ public Mono> acquireLease(String proposedID, int duration, ModifiedAccessConditions modifiedAccessConditions) { - return containerAsyncRawClient - .acquireLease(proposedID, duration, modifiedAccessConditions) + if (!this.validateNoEtag(modifiedAccessConditions)) { + // Throwing is preferred to Single.error because this will error out immediately instead of waiting until + // subscription. + throw new UnsupportedOperationException( + "ETag access conditions are not supported for this API."); + } + + return postProcessResponse(this.azureBlobStorage.containers().acquireLeaseWithRestResponseAsync( + null, null, duration, proposedID, null, modifiedAccessConditions, Context.NONE)) .map(rb -> new SimpleResponse<>(rb, rb.deserializedHeaders().leaseId())); } /** * Renews the blob's previously-acquired lease. * - * @param leaseID - * The leaseId of the active lease on the blob. - * - * @return - * A reactive response containing the renewed lease ID. + * @param leaseID The leaseId of the active lease on the blob. + * @return A reactive response containing the renewed lease ID. */ public Mono> renewLease(String leaseID) { return this.renewLease(leaseID, null); @@ -751,30 +815,32 @@ public Mono> renewLease(String leaseID) { /** * Renews the blob's previously-acquired lease. * - * @param leaseID - * The leaseId of the active lease on the blob. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * - * @return - * A reactive response containing the renewed lease ID. + * @param leaseID The leaseId of the active lease on the blob. + * @param modifiedAccessConditions Standard HTTP Access conditions related to the modification of data. ETag and + * LastModifiedTime are used to construct conditions related to when the blob was changed relative to the given + * request. The request will fail if the specified condition is not satisfied. + * @return A reactive response containing the renewed lease ID. + * @throws UnsupportedOperationException If either {@link ModifiedAccessConditions#ifMatch()} or {@link + * ModifiedAccessConditions#ifNoneMatch()} is set. */ public Mono> renewLease(String leaseID, ModifiedAccessConditions modifiedAccessConditions) { - return containerAsyncRawClient - .renewLease(leaseID, modifiedAccessConditions) + if (!this.validateNoEtag(modifiedAccessConditions)) { + // Throwing is preferred to Single.error because this will error out immediately instead of waiting until + // subscription. + throw new UnsupportedOperationException( + "ETag access conditions are not supported for this API."); + } + + return postProcessResponse(this.azureBlobStorage.containers().renewLeaseWithRestResponseAsync(null, + leaseID, null, null, modifiedAccessConditions, Context.NONE)) .map(rb -> new SimpleResponse<>(rb, rb.deserializedHeaders().leaseId())); } /** * Releases the blob's previously-acquired lease. * - * @param leaseID - * The leaseId of the active lease on the blob. - * - * @return - * A reactive response signalling completion. + * @param leaseID The leaseId of the active lease on the blob. + * @return A reactive response signalling completion. */ public Mono releaseLease(String leaseID) { return this.releaseLease(leaseID, null); @@ -783,19 +849,24 @@ public Mono releaseLease(String leaseID) { /** * Releases the blob's previously-acquired lease. * - * @param leaseID - * The leaseId of the active lease on the blob. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * - * @return - * A reactive response signalling completion. + * @param leaseID The leaseId of the active lease on the blob. + * @param modifiedAccessConditions Standard HTTP Access conditions related to the modification of data. ETag and + * LastModifiedTime are used to construct conditions related to when the blob was changed relative to the given + * request. The request will fail if the specified condition is not satisfied. + * @return A reactive response signalling completion. + * @throws UnsupportedOperationException If either {@link ModifiedAccessConditions#ifMatch()} or {@link + * ModifiedAccessConditions#ifNoneMatch()} is set. */ public Mono releaseLease(String leaseID, ModifiedAccessConditions modifiedAccessConditions) { - return containerAsyncRawClient - .releaseLease(leaseID, modifiedAccessConditions) + if (!this.validateNoEtag(modifiedAccessConditions)) { + // Throwing is preferred to Single.error because this will error out immediately instead of waiting until + // subscription. + throw new UnsupportedOperationException( + "ETag access conditions are not supported for this API."); + } + + return postProcessResponse(this.azureBlobStorage.containers().releaseLeaseWithRestResponseAsync( + null, leaseID, null, null, modifiedAccessConditions, Context.NONE)) .map(VoidResponse::new); } @@ -803,8 +874,7 @@ public Mono releaseLease(String leaseID, ModifiedAccessConditions * BreakLease breaks the blob's previously-acquired lease (if it exists). Pass the LeaseBreakDefault (-1) constant * to break a fixed-duration lease when it expires or an infinite lease immediately. * - * @return - * A reactive response containing the remaining time in the broken lease. + * @return A reactive response containing the remaining time in the broken lease. */ public Mono> breakLease() { return this.breakLease(null, null); @@ -814,58 +884,65 @@ public Mono> breakLease() { * BreakLease breaks the blob's previously-acquired lease (if it exists). Pass the LeaseBreakDefault (-1) constant * to break a fixed-duration lease when it expires or an infinite lease immediately. * - * @param breakPeriodInSeconds - * An optional {@code Integer} representing the proposed duration of seconds that the lease should continue - * before it is broken, between 0 and 60 seconds. This break period is only used if it is shorter than the - * time remaining on the lease. If longer, the time remaining on the lease is used. A new lease will not be - * available before the break period has expired, but the lease may be held for longer than the break - * period. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * - * @return - * A reactive response containing the remaining time in the broken lease. + * @param breakPeriodInSeconds An optional {@code Integer} representing the proposed duration of seconds that the + * lease should continue before it is broken, between 0 and 60 seconds. This break period is only used if it is + * shorter than the time remaining on the lease. If longer, the time remaining on the lease is used. A new lease + * will not be available before the break period has expired, but the lease may be held for longer than the break + * period. + * @param modifiedAccessConditions Standard HTTP Access conditions related to the modification of data. ETag and + * LastModifiedTime are used to construct conditions related to when the blob was changed relative to the given + * request. The request will fail if the specified condition is not satisfied. + * @return A reactive response containing the remaining time in the broken lease. + * @throws UnsupportedOperationException If either {@link ModifiedAccessConditions#ifMatch()} or {@link + * ModifiedAccessConditions#ifNoneMatch()} is set. */ public Mono> breakLease(Integer breakPeriodInSeconds, ModifiedAccessConditions modifiedAccessConditions) { - return containerAsyncRawClient - .breakLease(breakPeriodInSeconds, modifiedAccessConditions) + if (!this.validateNoEtag(modifiedAccessConditions)) { + // Throwing is preferred to Single.error because this will error out immediately instead of waiting until + // subscription. + throw new UnsupportedOperationException( + "ETag access conditions are not supported for this API."); + } + + return postProcessResponse(this.azureBlobStorage.containers().breakLeaseWithRestResponseAsync(null, + null, breakPeriodInSeconds, null, modifiedAccessConditions, Context.NONE)) .map(rb -> new SimpleResponse<>(rb, Duration.ofSeconds(rb.deserializedHeaders().leaseTime()))); } /** * ChangeLease changes the blob's lease ID. * - * @param leaseId - * The leaseId of the active lease on the blob. - * @param proposedID - * A {@code String} in any valid GUID format. - * - * @return - * A reactive response containing the new lease ID. + * @param leaseId The leaseId of the active lease on the blob. + * @param proposedID A {@code String} in any valid GUID format. + * @return A reactive response containing the new lease ID. */ public Mono> changeLease(String leaseId, String proposedID) { return this.changeLease(leaseId, proposedID, null); } /** - * ChangeLease changes the blob's lease ID. For more information, see the Azure Docs. - * - * @param leaseId - * The leaseId of the active lease on the blob. - * @param proposedID - * A {@code String} in any valid GUID format. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * + * ChangeLease changes the blob's lease ID. For more information, see the Azure + * Docs. + * + * @param leaseId The leaseId of the active lease on the blob. + * @param proposedID A {@code String} in any valid GUID format. + * @param modifiedAccessConditions Standard HTTP Access conditions related to the modification of data. ETag and + * LastModifiedTime are used to construct conditions related to when the blob was changed relative to the given + * request. The request will fail if the specified condition is not satisfied. * @return A reactive response containing the new lease ID. + * @throws UnsupportedOperationException If either {@link ModifiedAccessConditions#ifMatch()} or {@link + * ModifiedAccessConditions#ifNoneMatch()} is set. */ public Mono> changeLease(String leaseId, String proposedID, ModifiedAccessConditions modifiedAccessConditions) { - return containerAsyncRawClient - .changeLease(leaseId, proposedID, modifiedAccessConditions) + if (!this.validateNoEtag(modifiedAccessConditions)) { + // Throwing is preferred to Single.error because this will error out immediately instead of waiting until + // subscription. + throw new UnsupportedOperationException( + "ETag access conditions are not supported for this API."); + } + + return postProcessResponse(this.azureBlobStorage.containers().changeLeaseWithRestResponseAsync(null, + leaseId, proposedID, null, null, modifiedAccessConditions, Context.NONE)) .map(rb -> new SimpleResponse<>(rb, rb.deserializedHeaders().leaseId())); } @@ -873,63 +950,52 @@ public Mono> changeLease(String leaseId, String proposedID, Mod * Returns the sku name and account kind for the account. For more information, please see the * Azure Docs. * - * @return - * A reactive response containing the account info. + * @return A reactive response containing the account info. */ public Mono> getAccountInfo() { - return containerAsyncRawClient - .getAccountInfo() + return postProcessResponse( + this.azureBlobStorage.containers().getAccountInfoWithRestResponseAsync(null, Context.NONE)) .map(rb -> new SimpleResponse<>(rb, new StorageAccountInfo(rb.deserializedHeaders()))); } + private boolean validateNoEtag(ModifiedAccessConditions modifiedAccessConditions) { + if (modifiedAccessConditions == null) { + return true; + } + return modifiedAccessConditions.ifMatch() == null && modifiedAccessConditions.ifNoneMatch() == null; + } + /** * Generates a user delegation SAS with the specified parameters * - * @param userDelegationKey - * The {@code UserDelegationKey} user delegation key for the SAS - * @param accountName - * The {@code String} account name for the SAS - * @param permissions - * The {@code ContainerSASPermissions} permission for the SAS - * @param expiryTime - * The {@code OffsetDateTime} expiry time for the SAS - * - * @return - * A string that represents the SAS token + * @param userDelegationKey The {@code UserDelegationKey} user delegation key for the SAS + * @param accountName The {@code String} account name for the SAS + * @param permissions The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS + * @return A string that represents the SAS token */ public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, String accountName, - ContainerSASPermission permissions, OffsetDateTime expiryTime) { - return this.generateUserDelegationSAS(userDelegationKey, accountName, permissions, expiryTime, null /* - startTime */, null /* version */, null /* sasProtocol */, null /* ipRange */, null /* cacheControl */, null - /* contentDisposition */, null /* contentEncoding */, null /* contentLanguage */, null /* contentType */); + ContainerSASPermission permissions, OffsetDateTime expiryTime) { + return this.generateUserDelegationSAS(userDelegationKey, accountName, permissions, expiryTime, null, null, + null, null, null, null, null, null, null); } /** * Generates a user delegation SAS token with the specified parameters * - * @param userDelegationKey - * The {@code UserDelegationKey} user delegation key for the SAS - * @param accountName - * The {@code String} account name for the SAS - * @param permissions - * The {@code ContainerSASPermissions} permission for the SAS - * @param expiryTime - * The {@code OffsetDateTime} expiry time for the SAS - * @param startTime - * An optional {@code OffsetDateTime} start time for the SAS - * @param version - * An optional {@code String} version for the SAS - * @param sasProtocol - * An optional {@code SASProtocol} protocol for the SAS - * @param ipRange - * An optional {@code IPRange} ip address range for the SAS - * - * @return - * A string that represents the SAS token + * @param userDelegationKey The {@code UserDelegationKey} user delegation key for the SAS + * @param accountName The {@code String} account name for the SAS + * @param permissions The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS + * @param startTime An optional {@code OffsetDateTime} start time for the SAS + * @param version An optional {@code String} version for the SAS + * @param sasProtocol An optional {@code SASProtocol} protocol for the SAS + * @param ipRange An optional {@code IPRange} ip address range for the SAS + * @return A string that represents the SAS token */ public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, String accountName, - ContainerSASPermission permissions, OffsetDateTime expiryTime, OffsetDateTime startTime, String version, - SASProtocol sasProtocol, IPRange ipRange) { + ContainerSASPermission permissions, OffsetDateTime expiryTime, OffsetDateTime startTime, String version, + SASProtocol sasProtocol, IPRange ipRange) { return this.generateUserDelegationSAS(userDelegationKey, accountName, permissions, expiryTime, startTime, version, sasProtocol, ipRange, null /* cacheControl */, null /* contentDisposition */, null /* contentEncoding */, null /* contentLanguage */, null /* contentType */); @@ -938,40 +1004,25 @@ public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, Str /** * Generates a user delegation SAS token with the specified parameters * - * @param userDelegationKey - * The {@code UserDelegationKey} user delegation key for the SAS - * @param accountName - * The {@code String} account name for the SAS - * @param permissions - * The {@code ContainerSASPermissions} permission for the SAS - * @param expiryTime - * The {@code OffsetDateTime} expiry time for the SAS - * @param startTime - * An optional {@code OffsetDateTime} start time for the SAS - * @param version - * An optional {@code String} version for the SAS - * @param sasProtocol - * An optional {@code SASProtocol} protocol for the SAS - * @param ipRange - * An optional {@code IPRange} ip address range for the SAS - * @param cacheControl - * An optional {@code String} cache-control header for the SAS. - * @param contentDisposition - * An optional {@code String} content-disposition header for the SAS. - * @param contentEncoding - * An optional {@code String} content-encoding header for the SAS. - * @param contentLanguage - * An optional {@code String} content-language header for the SAS. - * @param contentType - * An optional {@code String} content-type header for the SAS. - * - * @return - * A string that represents the SAS token + * @param userDelegationKey The {@code UserDelegationKey} user delegation key for the SAS + * @param accountName The {@code String} account name for the SAS + * @param permissions The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS + * @param startTime An optional {@code OffsetDateTime} start time for the SAS + * @param version An optional {@code String} version for the SAS + * @param sasProtocol An optional {@code SASProtocol} protocol for the SAS + * @param ipRange An optional {@code IPRange} ip address range for the SAS + * @param cacheControl An optional {@code String} cache-control header for the SAS. + * @param contentDisposition An optional {@code String} content-disposition header for the SAS. + * @param contentEncoding An optional {@code String} content-encoding header for the SAS. + * @param contentLanguage An optional {@code String} content-language header for the SAS. + * @param contentType An optional {@code String} content-type header for the SAS. + * @return A string that represents the SAS token */ public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, String accountName, - ContainerSASPermission permissions, OffsetDateTime expiryTime, OffsetDateTime startTime, String version, - SASProtocol sasProtocol, IPRange ipRange, String cacheControl, String contentDisposition, - String contentEncoding, String contentLanguage, String contentType) { + ContainerSASPermission permissions, OffsetDateTime expiryTime, OffsetDateTime startTime, String version, + SASProtocol sasProtocol, IPRange ipRange, String cacheControl, String contentDisposition, + String contentEncoding, String contentLanguage, String contentType) { ServiceSASSignatureValues serviceSASSignatureValues = new ServiceSASSignatureValues(version, sasProtocol, startTime, expiryTime, permissions == null ? null : permissions.toString(), ipRange, null /* identifier*/, cacheControl, contentDisposition, contentEncoding, contentLanguage, contentType); @@ -986,13 +1037,9 @@ public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, Str /** * Generates a SAS token with the specified parameters * - * @param permissions - * The {@code ContainerSASPermissions} permission for the SAS - * @param expiryTime - * The {@code OffsetDateTime} expiry time for the SAS - * - * @return - * A string that represents the SAS token + * @param permissions The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS + * @return A string that represents the SAS token */ public String generateSAS(ContainerSASPermission permissions, OffsetDateTime expiryTime) { return this.generateSAS(null, permissions, /* identifier */ expiryTime, null /* startTime */, null /* version @@ -1003,11 +1050,8 @@ public String generateSAS(ContainerSASPermission permissions, OffsetDateTime exp /** * Generates a SAS token with the specified parameters * - * @param identifier - * The {@code String} name of the access policy on the container this SAS references if any - * - * @return - * A string that represents the SAS token + * @param identifier The {@code String} name of the access policy on the container this SAS references if any + * @return A string that represents the SAS token */ public String generateSAS(String identifier) { return this.generateSAS(identifier, null /* permissions*/, null /* expiryTime */, null /* startTime */, null @@ -1018,27 +1062,18 @@ public String generateSAS(String identifier) { /** * Generates a SAS token with the specified parameters * - * @param identifier - * The {@code String} name of the access policy on the container this SAS references if any - * @param permissions - * The {@code ContainerSASPermissions} permission for the SAS - * @param expiryTime - * The {@code OffsetDateTime} expiry time for the SAS - * @param startTime - * An optional {@code OffsetDateTime} start time for the SAS - * @param version - * An optional {@code String} version for the SAS - * @param sasProtocol - * An optional {@code SASProtocol} protocol for the SAS - * @param ipRange - * An optional {@code IPRange} ip address range for the SAS - * - * @return - * A string that represents the SAS token + * @param identifier The {@code String} name of the access policy on the container this SAS references if any + * @param permissions The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS + * @param startTime An optional {@code OffsetDateTime} start time for the SAS + * @param version An optional {@code String} version for the SAS + * @param sasProtocol An optional {@code SASProtocol} protocol for the SAS + * @param ipRange An optional {@code IPRange} ip address range for the SAS + * @return A string that represents the SAS token */ public String generateSAS(String identifier, ContainerSASPermission permissions, OffsetDateTime expiryTime, - OffsetDateTime startTime, - String version, SASProtocol sasProtocol, IPRange ipRange) { + OffsetDateTime startTime, + String version, SASProtocol sasProtocol, IPRange ipRange) { return this.generateSAS(identifier, permissions, expiryTime, startTime, version, sasProtocol, ipRange, null /* cacheControl */, null /* contentDisposition */, null /* contentEncoding */, null /* contentLanguage */, null /*contentType*/); @@ -1047,43 +1082,29 @@ public String generateSAS(String identifier, ContainerSASPermission permissions, /** * Generates a SAS token with the specified parameters * - * @param identifier - * The {@code String} name of the access policy on the container this SAS references if any - * @param permissions - * The {@code ContainerSASPermissions} permission for the SAS - * @param expiryTime - * The {@code OffsetDateTime} expiry time for the SAS - * @param startTime - * An optional {@code OffsetDateTime} start time for the SAS - * @param version - * An optional {@code String} version for the SAS - * @param sasProtocol - * An optional {@code SASProtocol} protocol for the SAS - * @param ipRange - * An optional {@code IPRange} ip address range for the SAS - * @param cacheControl - * An optional {@code String} cache-control header for the SAS. - * @param contentDisposition - * An optional {@code String} content-disposition header for the SAS. - * @param contentEncoding - * An optional {@code String} content-encoding header for the SAS. - * @param contentLanguage - * An optional {@code String} content-language header for the SAS. - * @param contentType - * An optional {@code String} content-type header for the SAS. - * - * @return - * A string that represents the SAS token + * @param identifier The {@code String} name of the access policy on the container this SAS references if any + * @param permissions The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS + * @param startTime An optional {@code OffsetDateTime} start time for the SAS + * @param version An optional {@code String} version for the SAS + * @param sasProtocol An optional {@code SASProtocol} protocol for the SAS + * @param ipRange An optional {@code IPRange} ip address range for the SAS + * @param cacheControl An optional {@code String} cache-control header for the SAS. + * @param contentDisposition An optional {@code String} content-disposition header for the SAS. + * @param contentEncoding An optional {@code String} content-encoding header for the SAS. + * @param contentLanguage An optional {@code String} content-language header for the SAS. + * @param contentType An optional {@code String} content-type header for the SAS. + * @return A string that represents the SAS token */ public String generateSAS(String identifier, ContainerSASPermission permissions, OffsetDateTime expiryTime, - OffsetDateTime startTime, String version, SASProtocol sasProtocol, IPRange ipRange, String cacheControl, - String contentDisposition, String contentEncoding, String contentLanguage, String contentType) { + OffsetDateTime startTime, String version, SASProtocol sasProtocol, IPRange ipRange, String cacheControl, + String contentDisposition, String contentEncoding, String contentLanguage, String contentType) { ServiceSASSignatureValues serviceSASSignatureValues = new ServiceSASSignatureValues(version, sasProtocol, startTime, expiryTime, permissions == null ? null : permissions.toString(), ipRange, identifier, cacheControl, contentDisposition, contentEncoding, contentLanguage, contentType); SharedKeyCredential sharedKeyCredential = - Utility.getSharedKeyCredential(this.containerAsyncRawClient.azureBlobStorage.httpPipeline()); + Utility.getSharedKeyCredential(this.azureBlobStorage.httpPipeline()); Utility.assertNotNull("sharedKeyCredential", sharedKeyCredential); @@ -1100,7 +1121,7 @@ public String generateSAS(String identifier, ContainerSASPermission permissions, */ private ServiceSASSignatureValues configureServiceSASSignatureValues(ServiceSASSignatureValues serviceSASSignatureValues, String accountName) { // Set canonical name - serviceSASSignatureValues.canonicalName(this.containerAsyncRawClient.azureBlobStorage.url(), accountName); + serviceSASSignatureValues.canonicalName(this.azureBlobStorage.url(), accountName); // Set snapshotId to null serviceSASSignatureValues.snapshotId(null); diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerAsyncRawClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerAsyncRawClient.java deleted file mode 100644 index e4106549b208c..0000000000000 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerAsyncRawClient.java +++ /dev/null @@ -1,708 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.azure.storage.blob; - -import com.azure.core.http.rest.Response; -import com.azure.core.http.rest.SimpleResponse; -import com.azure.core.util.Context; -import com.azure.storage.blob.implementation.AzureBlobStorageImpl; -import com.azure.storage.blob.models.BlobListDetails; -import com.azure.storage.blob.models.ContainerAccessConditions; -import com.azure.storage.blob.models.ContainerAccessPolicies; -import com.azure.storage.blob.models.ContainersAcquireLeaseResponse; -import com.azure.storage.blob.models.ContainersBreakLeaseResponse; -import com.azure.storage.blob.models.ContainersChangeLeaseResponse; -import com.azure.storage.blob.models.ContainersCreateResponse; -import com.azure.storage.blob.models.ContainersDeleteResponse; -import com.azure.storage.blob.models.ContainersGetAccountInfoResponse; -import com.azure.storage.blob.models.ContainersGetPropertiesResponse; -import com.azure.storage.blob.models.ContainersListBlobFlatSegmentResponse; -import com.azure.storage.blob.models.ContainersListBlobHierarchySegmentResponse; -import com.azure.storage.blob.models.ContainersReleaseLeaseResponse; -import com.azure.storage.blob.models.ContainersRenewLeaseResponse; -import com.azure.storage.blob.models.ContainersSetAccessPolicyResponse; -import com.azure.storage.blob.models.ContainersSetMetadataResponse; -import com.azure.storage.blob.models.LeaseAccessConditions; -import com.azure.storage.blob.models.ListBlobsOptions; -import com.azure.storage.blob.models.Metadata; -import com.azure.storage.blob.models.ModifiedAccessConditions; -import com.azure.storage.blob.models.PublicAccessType; -import com.azure.storage.blob.models.SignedIdentifier; -import reactor.core.publisher.Mono; - -import java.time.temporal.ChronoUnit; -import java.util.List; - -import static com.azure.storage.blob.Utility.postProcessResponse; - -/** - * Represents a URL to a container. It may be obtained by direct construction or via the create method on a - * {@link StorageAsyncRawClient} object. This class does not hold any state about a particular blob but is instead a convenient way - * of sending off appropriate requests to the resource on the service. It may also be used to construct URLs to blobs. - * Please refer to the - * Azure Docs - * for more information on containers. - */ -final class ContainerAsyncRawClient { - - public static final String ROOT_CONTAINER_NAME = "$root"; - - public static final String STATIC_WEBSITE_CONTAINER_NAME = "$web"; - - public static final String LOG_CONTAINER_NAME = "$logs"; - - AzureBlobStorageImpl azureBlobStorage; - - /** - * Creates a {@code ContainerAsyncClient} object pointing to the account specified by the URL and using the provided - * pipeline to make HTTP requests. - */ - ContainerAsyncRawClient(AzureBlobStorageImpl azureBlobStorage) { - this.azureBlobStorage = azureBlobStorage; - } - - /** - * Creates a new container within a storage account. If a container with the same name already exists, the operation - * fails. For more information, see the - * Azure Docs. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_basic "Sample code for ContainerAsyncClient.create")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono create() { - return this.create(null, null); - } - - /** - * Creates a new container within a storage account. If a container with the same name already exists, the operation - * fails. For more information, see the - * Azure Docs. - * - * @param metadata - * {@link Metadata} - * @param accessType - * Specifies how the data in this container is available to the public. See the x-ms-blob-public-access header - * in the Azure Docs for more information. Pass null for no public access. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_basic "Sample code for ContainerAsyncClient.create")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono create(Metadata metadata, PublicAccessType accessType) { - metadata = metadata == null ? new Metadata() : metadata; - - return postProcessResponse(this.azureBlobStorage.containers().createWithRestResponseAsync( - null, null, metadata, accessType, null, Context.NONE)); - - } - - /** - * Marks the specified container for deletion. The container and any blobs contained within it are later - * deleted during garbage collection. For more information, see the - * Azure Docs. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_basic "Sample code for ContainerAsyncClient.delete")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono delete() { - return this.delete(null); - } - - /** - * Marks the specified container for deletion. The container and any blobs contained within it are later - * deleted during garbage collection. For more information, see the - * Azure Docs. - * - * @param accessConditions - * {@link ContainerAccessConditions} - * - * @return Emits the successful response. - * @throws UnsupportedOperationException If {@link ContainerAccessConditions#modifiedAccessConditions()} has either - * {@link ModifiedAccessConditions#ifMatch()} or {@link ModifiedAccessConditions#ifNoneMatch()} set. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_basic "Sample code for ContainerAsyncClient.delete")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono delete(ContainerAccessConditions accessConditions) { - accessConditions = accessConditions == null ? new ContainerAccessConditions() : accessConditions; - - if (!validateNoEtag(accessConditions.modifiedAccessConditions())) { - // Throwing is preferred to Single.error because this will error out immediately instead of waiting until - // subscription. - throw new UnsupportedOperationException("ETag access conditions are not supported for this API."); - } - - return postProcessResponse(this.azureBlobStorage.containers() - .deleteWithRestResponseAsync(null, null, null, - accessConditions.leaseAccessConditions(), accessConditions.modifiedAccessConditions(), Context.NONE)); - } - - /** - * Returns the container's metadata and system properties. For more information, see the - * Azure Docs. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_basic "Sample code for ContainerAsyncClient.getProperties")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono getProperties() { - return this.getProperties(null); - } - - /** - * Returns the container's metadata and system properties. For more information, see the - * Azure Docs. - * - * @param leaseAccessConditions - * By setting lease access conditions, requests will fail if the provided lease does not match the active - * lease on the blob. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_basic "Sample code for ContainerAsyncClient.getProperties")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono getProperties(LeaseAccessConditions leaseAccessConditions) { - return postProcessResponse(this.azureBlobStorage.containers() - .getPropertiesWithRestResponseAsync(null, null, null, - leaseAccessConditions, Context.NONE)); - } - - /** - * Sets the container's metadata. For more information, see the - * Azure Docs. - * - * @param metadata - * {@link Metadata} - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_basic "Sample code for ContainerAsyncClient.setMetadata")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono setMetadata(Metadata metadata) { - return this.setMetadata(metadata, null); - } - - /** - * Sets the container's metadata. For more information, see the - * Azure Docs. - * - * @param metadata - * {@link Metadata} - * @param accessConditions - * {@link ContainerAccessConditions} - * - * @return Emits the successful response. - * @throws UnsupportedOperationException If {@link ContainerAccessConditions#modifiedAccessConditions()} has anything - * set other than {@link ModifiedAccessConditions#ifModifiedSince()}. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_basic "Sample code for ContainerAsyncClient.setMetadata")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono setMetadata(Metadata metadata, - ContainerAccessConditions accessConditions) { - metadata = metadata == null ? new Metadata() : metadata; - accessConditions = accessConditions == null ? new ContainerAccessConditions() : accessConditions; - if (!validateNoEtag(accessConditions.modifiedAccessConditions()) - || accessConditions.modifiedAccessConditions().ifUnmodifiedSince() != null) { - // Throwing is preferred to Single.error because this will error out immediately instead of waiting until - // subscription. - throw new UnsupportedOperationException( - "If-Modified-Since is the only HTTP access condition supported for this API"); - } - - return postProcessResponse(this.azureBlobStorage.containers() - .setMetadataWithRestResponseAsync(null, null, metadata, null, - accessConditions.leaseAccessConditions(), accessConditions.modifiedAccessConditions(), Context.NONE)); - } - - /** - * Returns the container's permissions. The permissions indicate whether container's blobs may be accessed publicly. - * For more information, see the - * Azure Docs. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_policy "Sample code for ContainerAsyncClient.getAccessPolicy")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono> getAccessPolicy() { - return this.getAccessPolicy(null); - } - - /** - * Returns the container's permissions. The permissions indicate whether container's blobs may be accessed publicly. - * For more information, see the - * Azure Docs. - * - * @param leaseAccessConditions - * By setting lease access conditions, requests will fail if the provided lease does not match the active - * lease on the blob. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_policy "Sample code for ContainerAsyncClient.getAccessPolicy")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono> getAccessPolicy(LeaseAccessConditions leaseAccessConditions) { - return postProcessResponse(this.azureBlobStorage.containers().getAccessPolicyWithRestResponseAsync(null, null, null, leaseAccessConditions, Context.NONE) - .map(response -> new SimpleResponse<>(response, new ContainerAccessPolicies(response.deserializedHeaders().blobPublicAccess(), response.value())))); - } - - /** - * Sets the container's permissions. The permissions indicate whether blobs in a container may be accessed publicly. - * Note that, for each signed identifier, we will truncate the start and expiry times to the nearest second to - * ensure the time formatting is compatible with the service. For more information, see the - * Azure Docs. - * - * @param accessType - * Specifies how the data in this container is available to the public. See the x-ms-blob-public-access header - * in the Azure Docs for more information. Pass null for no public access. - * @param identifiers - * A list of {@link SignedIdentifier} objects that specify the permissions for the container. Please see - * here - * for more information. Passing null will clear all access policies. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_policy "Sample code for ContainerAsyncClient.setAccessPolicy")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono setAccessPolicy(PublicAccessType accessType, - List identifiers) { - return this.setAccessPolicy(accessType, identifiers, null); - } - - /** - * Sets the container's permissions. The permissions indicate whether blobs in a container may be accessed publicly. - * Note that, for each signed identifier, we will truncate the start and expiry times to the nearest second to - * ensure the time formatting is compatible with the service. For more information, see the - * Azure Docs. - * - * @param accessType - * Specifies how the data in this container is available to the public. See the x-ms-blob-public-access header - * in the Azure Docs for more information. Pass null for no public access. - * @param identifiers - * A list of {@link SignedIdentifier} objects that specify the permissions for the container. Please see - * here - * for more information. Passing null will clear all access policies. - * @param accessConditions - * {@link ContainerAccessConditions} - * - * @return Emits the successful response. - * @throws UnsupportedOperationException If {@link ContainerAccessConditions#modifiedAccessConditions()} has either - * {@link ModifiedAccessConditions#ifMatch()} or {@link ModifiedAccessConditions#ifNoneMatch()} set. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_policy "Sample code for ContainerAsyncClient.setAccessPolicy")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono setAccessPolicy(PublicAccessType accessType, - List identifiers, ContainerAccessConditions accessConditions) { - accessConditions = accessConditions == null ? new ContainerAccessConditions() : accessConditions; - - if (!validateNoEtag(accessConditions.modifiedAccessConditions())) { - // Throwing is preferred to Single.error because this will error out immediately instead of waiting until - // subscription. - throw new UnsupportedOperationException("ETag access conditions are not supported for this API."); - } - - /* - We truncate to seconds because the service only supports nanoseconds or seconds, but doing an - OffsetDateTime.now will only give back milliseconds (more precise fields are zeroed and not serialized). This - allows for proper serialization with no real detriment to users as sub-second precision on active time for - signed identifiers is not really necessary. - */ - if (identifiers != null) { - for (SignedIdentifier identifier : identifiers) { - if (identifier.accessPolicy() != null && identifier.accessPolicy().start() != null) { - identifier.accessPolicy().start( - identifier.accessPolicy().start().truncatedTo(ChronoUnit.SECONDS)); - } - if (identifier.accessPolicy() != null && identifier.accessPolicy().expiry() != null) { - identifier.accessPolicy().expiry( - identifier.accessPolicy().expiry().truncatedTo(ChronoUnit.SECONDS)); - } - } - } - - return postProcessResponse(this.azureBlobStorage.containers() - .setAccessPolicyWithRestResponseAsync(null, identifiers, null, accessType, - null, accessConditions.leaseAccessConditions(), accessConditions.modifiedAccessConditions(), - Context.NONE)); - - } - - private boolean validateNoEtag(ModifiedAccessConditions modifiedAccessConditions) { - if (modifiedAccessConditions == null) { - return true; - } - return modifiedAccessConditions.ifMatch() == null && modifiedAccessConditions.ifNoneMatch() == null; - } - - /** - * Acquires a lease on the container for delete operations. The lease duration must be between 15 to - * 60 seconds, or infinite (-1). For more information, see the - * Azure Docs. - * - * @apiNote - * ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_lease "Sample code for ContainerAsyncClient.acquireLease")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/New-Storage-SDK-V10-Preview/src/test/java/com/microsoft/azure/storage/Samples.java) - * - * @param proposedId - * A {@code String} in any valid GUID format. - * @param duration - * The duration of the lease, in seconds, or negative one (-1) for a lease that never expires. - * A non-infinite lease can be between 15 and 60 seconds. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_lease "Sample code for ContainerAsyncClient.acquireLease")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono acquireLease(String proposedId, int duration) { - return this.acquireLease(proposedId, duration, null); - } - - /** - * Acquires a lease on the container for delete operations. The lease duration must be between 15 to - * 60 seconds, or infinite (-1). For more information, see the - * Azure Docs. - * - * @param proposedID - * A {@code String} in any valid GUID format. - * @param duration - * The duration of the lease, in seconds, or negative one (-1) for a lease that never expires. - * A non-infinite lease can be between 15 and 60 seconds. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * - * @return Emits the successful response. - * @throws UnsupportedOperationException If either {@link ModifiedAccessConditions#ifMatch()} or - * {@link ModifiedAccessConditions#ifNoneMatch()} is set. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_lease "Sample code for ContainerAsyncClient.acquireLease")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono acquireLease(String proposedID, int duration, - ModifiedAccessConditions modifiedAccessConditions) { - if (!this.validateNoEtag(modifiedAccessConditions)) { - // Throwing is preferred to Single.error because this will error out immediately instead of waiting until - // subscription. - throw new UnsupportedOperationException( - "ETag access conditions are not supported for this API."); - } - - return postProcessResponse(this.azureBlobStorage.containers().acquireLeaseWithRestResponseAsync( - null, null, duration, proposedID, null, modifiedAccessConditions, Context.NONE)); - } - - /** - * Renews the container's previously-acquired lease. For more information, see the - * Azure Docs. - * - * @param leaseID - * The leaseId of the active lease on the container. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_lease "Sample code for ContainerAsyncClient.renewLease")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono renewLease(String leaseID) { - return this.renewLease(leaseID, null); - } - - /** - * Renews the container's previously-acquired lease. For more information, see the - * Azure Docs. - * - * @param leaseID - * The leaseId of the active lease on the container. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * - * @return Emits the successful response. - * @throws UnsupportedOperationException If either {@link ModifiedAccessConditions#ifMatch()} or - * {@link ModifiedAccessConditions#ifNoneMatch()} is set. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_lease "Sample code for ContainerAsyncClient.renewLease")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono renewLease(String leaseID, - ModifiedAccessConditions modifiedAccessConditions) { - if (!this.validateNoEtag(modifiedAccessConditions)) { - // Throwing is preferred to Single.error because this will error out immediately instead of waiting until - // subscription. - throw new UnsupportedOperationException( - "ETag access conditions are not supported for this API."); - } - - return postProcessResponse(this.azureBlobStorage.containers().renewLeaseWithRestResponseAsync(null, - leaseID, null, null, modifiedAccessConditions, Context.NONE)); - } - - /** - * Releases the container's previously-acquired lease. For more information, see the - * Azure Docs. - * - * @param leaseID - * The leaseId of the active lease on the container. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_lease "Sample code for ContainerAsyncClient.releaseLease")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono releaseLease(String leaseID) { - return this.releaseLease(leaseID, null); - } - - /** - * Releases the container's previously-acquired lease. For more information, see the - * Azure Docs. - * - * @param leaseID - * The leaseId of the active lease on the container. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * - * @return Emits the successful response. - * @throws UnsupportedOperationException If either {@link ModifiedAccessConditions#ifMatch()} or - * {@link ModifiedAccessConditions#ifNoneMatch()} is set. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_lease "Sample code for ContainerAsyncClient.releaseLease")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono releaseLease(String leaseID, - ModifiedAccessConditions modifiedAccessConditions) { - if (!this.validateNoEtag(modifiedAccessConditions)) { - // Throwing is preferred to Single.error because this will error out immediately instead of waiting until - // subscription. - throw new UnsupportedOperationException( - "ETag access conditions are not supported for this API."); - } - - return postProcessResponse(this.azureBlobStorage.containers().releaseLeaseWithRestResponseAsync( - null, leaseID, null, null, modifiedAccessConditions, Context.NONE)); - } - - /** - * Breaks the container's previously-acquired lease. For more information, see the - * Azure Docs. - * - * @apiNote - * ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_lease "Sample code for ContainerAsyncClient.breakLease")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/New-Storage-SDK-V10-Preview/src/test/java/com/microsoft/azure/storage/Samples.java) - * - * @return Emits the successful response. - */ - public Mono breakLease() { - return this.breakLease(null, null); - } - - /** - * Breaks the container's previously-acquired lease. For more information, see the - * Azure Docs. - * - * @param breakPeriodInSeconds - * An optional {@code Integer} representing the proposed duration of seconds that the lease should continue - * before it is broken, between 0 and 60 seconds. This break period is only used if it is shorter than the time - * remaining on the lease. If longer, the time remaining on the lease is used. A new lease will not be - * available before the break period has expired, but the lease may be held for longer than the break period. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * - * @return Emits the successful response. - * @throws UnsupportedOperationException If either {@link ModifiedAccessConditions#ifMatch()} or - * {@link ModifiedAccessConditions#ifNoneMatch()} is set. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_lease "Sample code for ContainerAsyncClient.breakLease")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono breakLease(Integer breakPeriodInSeconds, - ModifiedAccessConditions modifiedAccessConditions) { - if (!this.validateNoEtag(modifiedAccessConditions)) { - // Throwing is preferred to Single.error because this will error out immediately instead of waiting until - // subscription. - throw new UnsupportedOperationException( - "ETag access conditions are not supported for this API."); - } - - return postProcessResponse(this.azureBlobStorage.containers().breakLeaseWithRestResponseAsync(null, - null, breakPeriodInSeconds, null, modifiedAccessConditions, Context.NONE)); - - } - - /** - * Changes the container's leaseAccessConditions. For more information, see the - * Azure Docs. - * - * @param leaseID - * The leaseId of the active lease on the container. - * @param proposedID - * A {@code String} in any valid GUID format. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_lease "Sample code for ContainerAsyncClient.changeLease")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono changeLease(String leaseID, String proposedID) { - return this.changeLease(leaseID, proposedID, null); - } - - /** - * Changes the container's leaseAccessConditions. For more information, see the - * Azure Docs. - * - * @param leaseID - * The leaseId of the active lease on the container. - * @param proposedID - * A {@code String} in any valid GUID format. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * - * @return Emits the successful response. - * @throws UnsupportedOperationException If either {@link ModifiedAccessConditions#ifMatch()} or - * {@link ModifiedAccessConditions#ifNoneMatch()} is set. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_lease "Sample code for ContainerAsyncClient.changeLease")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono changeLease(String leaseID, String proposedID, - ModifiedAccessConditions modifiedAccessConditions) { - if (!this.validateNoEtag(modifiedAccessConditions)) { - // Throwing is preferred to Single.error because this will error out immediately instead of waiting until - // subscription. - throw new UnsupportedOperationException( - "ETag access conditions are not supported for this API."); - } - - return postProcessResponse(this.azureBlobStorage.containers().changeLeaseWithRestResponseAsync(null, - leaseID, proposedID, null, null, modifiedAccessConditions, Context.NONE)); - } - - /** - * Returns a single segment of blobs starting from the specified Marker. Use an empty - * marker to start enumeration from the beginning. Blob names are returned in lexicographic order. - * After getting a segment, process it, and then call ListBlobs again (passing the the previously-returned - * Marker) to get the next segment. For more information, see the - * Azure Docs. - * - * @param marker - * Identifies the portion of the list to be returned with the next list operation. - * This value is returned in the response of a previous list operation as the - * ListBlobsFlatSegmentResponse.body().nextMarker(). Set to null to list the first segment. - * @param options - * {@link ListBlobsOptions} - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=list_blobs_flat "Sample code for ContainerAsyncClient.listBlobsFlatSegment")] \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=list_blobs_flat_helper "helper code for ContainerAsyncClient.listBlobsFlatSegment")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono listBlobsFlatSegment(String marker, ListBlobsOptions options) { - options = options == null ? new ListBlobsOptions() : options; - - return postProcessResponse(this.azureBlobStorage.containers() - .listBlobFlatSegmentWithRestResponseAsync(null, options.prefix(), marker, - options.maxResults(), options.details().toList(), null, null, Context.NONE)); - } - - /** - * Returns a single segment of blobs and blob prefixes starting from the specified Marker. Use an empty - * marker to start enumeration from the beginning. Blob names are returned in lexicographic order. - * After getting a segment, process it, and then call ListBlobs again (passing the the previously-returned - * Marker) to get the next segment. For more information, see the - * Azure Docs. - * - * @param marker - * Identifies the portion of the list to be returned with the next list operation. - * This value is returned in the response of a previous list operation as the - * ListBlobsHierarchySegmentResponse.body().nextMarker(). Set to null to list the first segment. - * @param delimiter - * The operation returns a BlobPrefix element in the response body that acts as a placeholder for all blobs - * whose names begin with the same substring up to the appearance of the delimiter character. The delimiter may - * be a single character or a string. - * @param options - * {@link ListBlobsOptions} - * - * @return Emits the successful response. - * @throws UnsupportedOperationException If {@link ListBlobsOptions#details()} has {@link BlobListDetails#snapshots()} - * set. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=list_blobs_hierarchy "Sample code for ContainerAsyncClient.listBlobsHierarchySegment")] \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=list_blobs_hierarchy_helper "helper code for ContainerAsyncClient.listBlobsHierarchySegment")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono listBlobsHierarchySegment(String marker, String delimiter, - ListBlobsOptions options) { - options = options == null ? new ListBlobsOptions() : options; - if (options.details().snapshots()) { - throw new UnsupportedOperationException("Including snapshots in a hierarchical listing is not supported."); - } - - return postProcessResponse(this.azureBlobStorage.containers() - .listBlobHierarchySegmentWithRestResponseAsync(null, delimiter, options.prefix(), marker, - options.maxResults(), options.details().toList(), null, null, Context.NONE)); - } - - /** - * Returns the sku name and account kind for the account. For more information, please see the - * Azure Docs. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=account_info "Sample code for ContainerAsyncClient.getAccountInfo")] \n - * For more samples, please see the [Samples file] (https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono getAccountInfo() { - return postProcessResponse( - this.azureBlobStorage.containers().getAccountInfoWithRestResponseAsync(null, Context.NONE)); - } -} diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerClient.java index c9733fd3a7f61..de5d4f1431f39 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerClient.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerClient.java @@ -25,47 +25,45 @@ import java.util.List; /** - * Client to a container. It may only be instantiated through a {@link ContainerClientBuilder} or via the method - * {@link StorageClient#getContainerClient(String)}. This class does not hold any - * state about a particular container but is instead a convenient way of sending off appropriate requests to - * the resource on the service. It may also be used to construct URLs to blobs. + * Client to a container. It may only be instantiated through a {@link ContainerClientBuilder} or via the method {@link + * StorageClient#getContainerClient(String)}. This class does not hold any state about a particular container but is + * instead a convenient way of sending off appropriate requests to the resource on the service. It may also be used to + * construct URLs to blobs. * *

* This client contains operations on a container. Operations on a blob are available on {@link BlobClient} through * {@link #getBlobClient(String)}, and operations on the service are available on {@link StorageClient}. * *

- * Please refer to the Azure Docs - * for more information on containers. + * Please refer to the Azure + * Docs for more information on containers. */ public final class ContainerClient { - private ContainerAsyncClient containerAsyncClient; - public static final String ROOT_CONTAINER_NAME = "$root"; + public static final String ROOT_CONTAINER_NAME = ContainerAsyncClient.ROOT_CONTAINER_NAME; - public static final String STATIC_WEBSITE_CONTAINER_NAME = "$web"; + public static final String STATIC_WEBSITE_CONTAINER_NAME = ContainerAsyncClient.STATIC_WEBSITE_CONTAINER_NAME; - public static final String LOG_CONTAINER_NAME = "$logs"; + public static final String LOG_CONTAINER_NAME = ContainerAsyncClient.LOG_CONTAINER_NAME; /** * Package-private constructor for use by {@link ContainerClientBuilder}. + * * @param containerAsyncClient the async container client */ ContainerClient(ContainerAsyncClient containerAsyncClient) { - this.containerAsyncClient = containerAsyncClient; + this.containerAsyncClient = containerAsyncClient; } /** - * Creates a new {@link BlockBlobClient} object by concatenating the blobName to the end of - * ContainerAsyncClient's URL. The new BlockBlobClient uses the same request policy pipeline as the ContainerAsyncClient. - * To change the pipeline, create the BlockBlobClient and then call its WithPipeline method passing in the - * desired pipeline object. Or, call this package's NewBlockBlobAsyncClient instead of calling this object's - * NewBlockBlobAsyncClient method. - * - * @param blobName - * A {@code String} representing the name of the blob. + * Creates a new {@link BlockBlobClient} object by concatenating the blobName to the end of ContainerAsyncClient's + * URL. The new BlockBlobClient uses the same request policy pipeline as the ContainerAsyncClient. To change the + * pipeline, create the BlockBlobClient and then call its WithPipeline method passing in the desired pipeline + * object. Or, call this package's NewBlockBlobAsyncClient instead of calling this object's NewBlockBlobAsyncClient + * method. * + * @param blobName A {@code String} representing the name of the blob. * @return A new {@link BlockBlobClient} object which references the blob with the specified name in this container. */ public BlockBlobClient getBlockBlobClient(String blobName) { @@ -73,17 +71,14 @@ public BlockBlobClient getBlockBlobClient(String blobName) { } /** - * Creates a new {@link BlockBlobClient} object by concatenating the blobName to the end of - * ContainerAsyncClient's URL. The new BlockBlobClient uses the same request policy pipeline as the ContainerAsyncClient. - * To change the pipeline, create the BlockBlobClient and then call its WithPipeline method passing in the - * desired pipeline object. Or, call this package's NewBlockBlobAsyncClient instead of calling this object's - * NewBlockBlobAsyncClient method. - * - * @param blobName - * A {@code String} representing the name of the blob. - * @param snapshot - * the snapshot identifier for the blob. + * Creates a new {@link BlockBlobClient} object by concatenating the blobName to the end of ContainerAsyncClient's + * URL. The new BlockBlobClient uses the same request policy pipeline as the ContainerAsyncClient. To change the + * pipeline, create the BlockBlobClient and then call its WithPipeline method passing in the desired pipeline + * object. Or, call this package's NewBlockBlobAsyncClient instead of calling this object's NewBlockBlobAsyncClient + * method. * + * @param blobName A {@code String} representing the name of the blob. + * @param snapshot the snapshot identifier for the blob. * @return A new {@link BlockBlobClient} object which references the blob with the specified name in this container. */ public BlockBlobClient getBlockBlobClient(String blobName, String snapshot) { @@ -91,15 +86,12 @@ public BlockBlobClient getBlockBlobClient(String blobName, String snapshot) { } /** - * Creates creates a new PageBlobClient object by concatenating blobName to the end of - * ContainerAsyncClient's URL. The new PageBlobClient uses the same request policy pipeline as the ContainerAsyncClient. - * To change the pipeline, create the PageBlobClient and then call its WithPipeline method passing in the - * desired pipeline object. Or, call this package's NewPageBlobAsyncClient instead of calling this object's - * NewPageBlobAsyncClient method. - * - * @param blobName - * A {@code String} representing the name of the blob. + * Creates creates a new PageBlobClient object by concatenating blobName to the end of ContainerAsyncClient's URL. + * The new PageBlobClient uses the same request policy pipeline as the ContainerAsyncClient. To change the pipeline, + * create the PageBlobClient and then call its WithPipeline method passing in the desired pipeline object. Or, call + * this package's NewPageBlobAsyncClient instead of calling this object's NewPageBlobAsyncClient method. * + * @param blobName A {@code String} representing the name of the blob. * @return A new {@link PageBlobClient} object which references the blob with the specified name in this container. */ public PageBlobClient getPageBlobClient(String blobName) { @@ -107,17 +99,13 @@ public PageBlobClient getPageBlobClient(String blobName) { } /** - * Creates creates a new PageBlobClient object by concatenating blobName to the end of - * ContainerAsyncClient's URL. The new PageBlobClient uses the same request policy pipeline as the ContainerAsyncClient. - * To change the pipeline, create the PageBlobClient and then call its WithPipeline method passing in the - * desired pipeline object. Or, call this package's NewPageBlobAsyncClient instead of calling this object's - * NewPageBlobAsyncClient method. - * - * @param blobName - * A {@code String} representing the name of the blob. - * @param snapshot - * the snapshot identifier for the blob. + * Creates creates a new PageBlobClient object by concatenating blobName to the end of ContainerAsyncClient's URL. + * The new PageBlobClient uses the same request policy pipeline as the ContainerAsyncClient. To change the pipeline, + * create the PageBlobClient and then call its WithPipeline method passing in the desired pipeline object. Or, call + * this package's NewPageBlobAsyncClient instead of calling this object's NewPageBlobAsyncClient method. * + * @param blobName A {@code String} representing the name of the blob. + * @param snapshot the snapshot identifier for the blob. * @return A new {@link PageBlobClient} object which references the blob with the specified name in this container. */ public PageBlobClient getPageBlobClient(String blobName, String snapshot) { @@ -125,31 +113,27 @@ public PageBlobClient getPageBlobClient(String blobName, String snapshot) { } /** - * Creates creates a new AppendBlobClient object by concatenating blobName to the end of - * ContainerAsyncClient's URL. The new AppendBlobClient uses the same request policy pipeline as the ContainerAsyncClient. - * To change the pipeline, create the AppendBlobClient and then call its WithPipeline method passing in the - * desired pipeline object. Or, call this package's NewAppendBlobAsyncClient instead of calling this object's + * Creates creates a new AppendBlobClient object by concatenating blobName to the end of ContainerAsyncClient's URL. + * The new AppendBlobClient uses the same request policy pipeline as the ContainerAsyncClient. To change the + * pipeline, create the AppendBlobClient and then call its WithPipeline method passing in the desired pipeline + * object. Or, call this package's NewAppendBlobAsyncClient instead of calling this object's * NewAppendBlobAsyncClient method. * - * @param blobName - * A {@code String} representing the name of the blob. - * - * @return A new {@link AppendBlobClient} object which references the blob with the specified name in this container. + * @param blobName A {@code String} representing the name of the blob. + * @return A new {@link AppendBlobClient} object which references the blob with the specified name in this + * container. */ public AppendBlobClient getAppendBlobClient(String blobName) { return new AppendBlobClient(containerAsyncClient.getAppendBlobAsyncClient(blobName)); } /** - * Initializes a new BlobClient object by concatenating blobName to the end of - * ContainerAsyncClient's URL. The new BlobClient uses the same request policy pipeline as the ContainerAsyncClient. - * To change the pipeline, create the BlobClient and then call its WithPipeline method passing in the - * desired pipeline object. Or, call this package's getBlobAsyncClient instead of calling this object's - * getBlobAsyncClient method. - * - * @param blobName - * A {@code String} representing the name of the blob. + * Initializes a new BlobClient object by concatenating blobName to the end of ContainerAsyncClient's URL. The new + * BlobClient uses the same request policy pipeline as the ContainerAsyncClient. To change the pipeline, create the + * BlobClient and then call its WithPipeline method passing in the desired pipeline object. Or, call this package's + * getBlobAsyncClient instead of calling this object's getBlobAsyncClient method. * + * @param blobName A {@code String} representing the name of the blob. * @return A new {@link BlobClient} object which references the blob with the specified name in this container. */ public BlobClient getBlobClient(String blobName) { @@ -157,17 +141,13 @@ public BlobClient getBlobClient(String blobName) { } /** - * Initializes a new BlobClient object by concatenating blobName to the end of - * ContainerAsyncClient's URL. The new BlobClient uses the same request policy pipeline as the ContainerAsyncClient. - * To change the pipeline, create the BlobClient and then call its WithPipeline method passing in the - * desired pipeline object. Or, call this package's getBlobAsyncClient instead of calling this object's - * getBlobAsyncClient method. - * - * @param blobName - * A {@code String} representing the name of the blob. - * @param snapshot - * the snapshot identifier for the blob. + * Initializes a new BlobClient object by concatenating blobName to the end of ContainerAsyncClient's URL. The new + * BlobClient uses the same request policy pipeline as the ContainerAsyncClient. To change the pipeline, create the + * BlobClient and then call its WithPipeline method passing in the desired pipeline object. Or, call this package's + * getBlobAsyncClient instead of calling this object's getBlobAsyncClient method. * + * @param blobName A {@code String} representing the name of the blob. + * @param snapshot the snapshot identifier for the blob. * @return A new {@link BlobClient} object which references the blob with the specified name in this container. */ public BlobClient getBlobClient(String blobName, String snapshot) { @@ -177,8 +157,7 @@ public BlobClient getBlobClient(String blobName, String snapshot) { /** * Initializes a {@link StorageClient} object pointing to the storage account this container is in. * - * @return - * A {@link StorageClient} object pointing to the specified storage account + * @return A {@link StorageClient} object pointing to the specified storage account */ public StorageClient getStorageClient() { return new StorageClient(containerAsyncClient.getStorageAsyncClient()); @@ -186,6 +165,7 @@ public StorageClient getStorageClient() { /** * Gets the URL of the container represented by this client. + * * @return the URL. */ public URL getContainerUrl() { @@ -204,10 +184,8 @@ public Response exists() { /** * Gets if the container this client represents exists in the cloud. * - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. - * @return - * true if the container exists, false if it doesn't + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @return true if the container exists, false if it doesn't */ public Response exists(Duration timeout) { Mono> response = containerAsyncClient.exists(); @@ -219,6 +197,7 @@ public Response exists(Duration timeout) { * Creates a new container within a storage account. If a container with the same name already exists, the operation * fails. For more information, see the * Azure Docs. + * * @return A response containing status code and HTTP headers */ public VoidResponse create() { @@ -230,13 +209,10 @@ public VoidResponse create() { * fails. For more information, see the * Azure Docs. * - * @param metadata - * {@link Metadata} - * @param accessType - * Specifies how the data in this container is available to the public. See the x-ms-blob-public-access header - * in the Azure Docs for more information. Pass null for no public access. - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @param metadata {@link Metadata} + * @param accessType Specifies how the data in this container is available to the public. See the + * x-ms-blob-public-access header in the Azure Docs for more information. Pass null for no public access. + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. * @return A response containing status code and HTTP headers */ public VoidResponse create(Metadata metadata, PublicAccessType accessType, Duration timeout) { @@ -246,9 +222,10 @@ public VoidResponse create(Metadata metadata, PublicAccessType accessType, Durat } /** - * Marks the specified container for deletion. The container and any blobs contained within it are later - * deleted during garbage collection. For more information, see the + * Marks the specified container for deletion. The container and any blobs contained within it are later deleted + * during garbage collection. For more information, see the * Azure Docs. + * * @return A response containing status code and HTTP headers */ public VoidResponse delete() { @@ -256,14 +233,12 @@ public VoidResponse delete() { } /** - * Marks the specified container for deletion. The container and any blobs contained within it are later - * deleted during garbage collection. For more information, see the + * Marks the specified container for deletion. The container and any blobs contained within it are later deleted + * during garbage collection. For more information, see the * Azure Docs. * - * @param accessConditions - * {@link ContainerAccessConditions} - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @param accessConditions {@link ContainerAccessConditions} + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. * @return A response containing status code and HTTP headers */ public VoidResponse delete(ContainerAccessConditions accessConditions, Duration timeout) { @@ -276,8 +251,7 @@ public VoidResponse delete(ContainerAccessConditions accessConditions, Duration * Returns the container's metadata and system properties. For more information, see the * Azure Docs. * - * @return - * The container properties. + * @return The container properties. */ public Response getProperties() { return this.getProperties(null, null); @@ -287,17 +261,13 @@ public Response getProperties() { * Returns the container's metadata and system properties. For more information, see the * Azure Docs. * - * @param leaseAccessConditions - * By setting lease access conditions, requests will fail if the provided lease does not match the active - * lease on the blob. - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. - * - * @return - * The container properties. + * @param leaseAccessConditions By setting lease access conditions, requests will fail if the provided lease does + * not match the active lease on the blob. + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @return The container properties. */ public Response getProperties(LeaseAccessConditions leaseAccessConditions, - Duration timeout) { + Duration timeout) { Mono> response = containerAsyncClient.getProperties(leaseAccessConditions); return Utility.blockWithOptionalTimeout(response, timeout); @@ -307,8 +277,7 @@ public Response getProperties(LeaseAccessConditions leaseAc * Sets the container's metadata. For more information, see the * Azure Docs. * - * @param metadata - * {@link Metadata} + * @param metadata {@link Metadata} * @return A response containing status code and HTTP headers */ public VoidResponse setMetadata(Metadata metadata) { @@ -319,16 +288,13 @@ public VoidResponse setMetadata(Metadata metadata) { * Sets the container's metadata. For more information, see the * Azure Docs. * - * @param metadata - * {@link Metadata} - * @param accessConditions - * {@link ContainerAccessConditions} - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @param metadata {@link Metadata} + * @param accessConditions {@link ContainerAccessConditions} + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. * @return A response containing status code and HTTP headers */ public VoidResponse setMetadata(Metadata metadata, - ContainerAccessConditions accessConditions, Duration timeout) { + ContainerAccessConditions accessConditions, Duration timeout) { Mono response = containerAsyncClient.setMetadata(metadata, accessConditions); return Utility.blockWithOptionalTimeout(response, timeout); @@ -339,8 +305,7 @@ public VoidResponse setMetadata(Metadata metadata, * For more information, see the * Azure Docs. * - * @return - * The container access policy. + * @return The container access policy. */ public Response getAccessPolicy() { return this.getAccessPolicy(null, null); @@ -351,14 +316,10 @@ public Response getAccessPolicy() { * For more information, see the * Azure Docs. * - * @param leaseAccessConditions - * By setting lease access conditions, requests will fail if the provided lease does not match the active - * lease on the blob. - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. - * - * @return - * The container access policy. + * @param leaseAccessConditions By setting lease access conditions, requests will fail if the provided lease does + * not match the active lease on the blob. + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @return The container access policy. */ public Response getAccessPolicy(LeaseAccessConditions leaseAccessConditions, Duration timeout) { @@ -373,17 +334,16 @@ public Response getAccessPolicy(LeaseAccessConditions l * ensure the time formatting is compatible with the service. For more information, see the * Azure Docs. * - * @param accessType - * Specifies how the data in this container is available to the public. See the x-ms-blob-public-access header - * in the Azure Docs for more information. Pass null for no public access. - * @param identifiers - * A list of {@link SignedIdentifier} objects that specify the permissions for the container. Please see - * here - * for more information. Passing null will clear all access policies. + * @param accessType Specifies how the data in this container is available to the public. See the + * x-ms-blob-public-access header in the Azure Docs for more information. Pass null for no public access. + * @param identifiers A list of {@link SignedIdentifier} objects that specify the permissions for the container. + * Please see + * here + * for more information. Passing null will clear all access policies. * @return A response containing status code and HTTP headers */ public VoidResponse setAccessPolicy(PublicAccessType accessType, - List identifiers) { + List identifiers) { return this.setAccessPolicy(accessType, identifiers, null, null); } @@ -393,31 +353,27 @@ public VoidResponse setAccessPolicy(PublicAccessType accessType, * ensure the time formatting is compatible with the service. For more information, see the * Azure Docs. * - * @param accessType - * Specifies how the data in this container is available to the public. See the x-ms-blob-public-access header - * in the Azure Docs for more information. Pass null for no public access. - * @param identifiers - * A list of {@link SignedIdentifier} objects that specify the permissions for the container. Please see - * here - * for more information. Passing null will clear all access policies. - * @param accessConditions - * {@link ContainerAccessConditions} - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @param accessType Specifies how the data in this container is available to the public. See the + * x-ms-blob-public-access header in the Azure Docs for more information. Pass null for no public access. + * @param identifiers A list of {@link SignedIdentifier} objects that specify the permissions for the container. + * Please see + * here + * for more information. Passing null will clear all access policies. + * @param accessConditions {@link ContainerAccessConditions} + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. * @return A response containing status code and HTTP headers */ public VoidResponse setAccessPolicy(PublicAccessType accessType, - List identifiers, ContainerAccessConditions accessConditions, - Duration timeout) { + List identifiers, ContainerAccessConditions accessConditions, + Duration timeout) { Mono response = containerAsyncClient.setAccessPolicy(accessType, identifiers, accessConditions); return Utility.blockWithOptionalTimeout(response, timeout); } /** - * Returns a lazy loaded list of blobs in this container, with folder structures flattened. - * The returned {@link Iterable} can be iterated through while new items are automatically - * retrieved as needed. + * Returns a lazy loaded list of blobs in this container, with folder structures flattened. The returned {@link + * Iterable} can be iterated through while new items are automatically retrieved as needed. * *

* Blob names are returned in lexicographic order. @@ -426,17 +382,15 @@ public VoidResponse setAccessPolicy(PublicAccessType accessType, * For more information, see the * Azure Docs. * - * @return - * The listed blobs, flattened. + * @return The listed blobs, flattened. */ public Iterable listBlobsFlat() { return this.listBlobsFlat(new ListBlobsOptions(), null); } /** - * Returns a lazy loaded list of blobs in this container, with folder structures flattened. - * The returned {@link Iterable} can be iterated through while new items are automatically - * retrieved as needed. + * Returns a lazy loaded list of blobs in this container, with folder structures flattened. The returned {@link + * Iterable} can be iterated through while new items are automatically retrieved as needed. * *

* Blob names are returned in lexicographic order. @@ -445,13 +399,9 @@ public Iterable listBlobsFlat() { * For more information, see the * Azure Docs. * - * @param options - * {@link ListBlobsOptions} - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. - * - * @return - * The listed blobs, flattened. + * @param options {@link ListBlobsOptions} + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @return The listed blobs, flattened. */ public Iterable listBlobsFlat(ListBlobsOptions options, Duration timeout) { Flux response = containerAsyncClient.listBlobsFlat(options); @@ -460,74 +410,64 @@ public Iterable listBlobsFlat(ListBlobsOptions options, Duration timeo } /** - * Returns a reactive Publisher emitting all the blobs and directories (prefixes) under - * the given directory (prefix). Directories will have {@link BlobItem#isPrefix()} set to - * true. + * Returns a reactive Publisher emitting all the blobs and directories (prefixes) under the given directory + * (prefix). Directories will have {@link BlobItem#isPrefix()} set to true. * *

* Blob names are returned in lexicographic order. For more information, see the * Azure Docs. * *

- * E.g. listing a container containing a 'foo' folder, which contains blobs 'foo1' and 'foo2', and a blob - * on the root level 'bar', will return the following results when prefix=null: + * E.g. listing a container containing a 'foo' folder, which contains blobs 'foo1' and 'foo2', and a blob on the + * root level 'bar', will return the following results when prefix=null: * *

    - *
  • foo/ (isPrefix = true) - *
  • bar (isPrefix = false) + *
  • foo/ (isPrefix = true) + *
  • bar (isPrefix = false) *
*

* will return the following results when prefix="foo/": * *

    - *
  • foo/foo1 (isPrefix = false) - *
  • foo/foo2 (isPrefix = false) + *
  • foo/foo1 (isPrefix = false) + *
  • foo/foo2 (isPrefix = false) *
* - * @param directory - * The directory to list blobs underneath - * - * @return - * A reactive response emitting the prefixes and blobs. + * @param directory The directory to list blobs underneath + * @return A reactive response emitting the prefixes and blobs. */ public Iterable listBlobsHierarchy(String directory) { return this.listBlobsHierarchy("/", new ListBlobsOptions().prefix(directory), null); } /** - * Returns a reactive Publisher emitting all the blobs and prefixes (directories) under - * the given prefix (directory). Directories will have {@link BlobItem#isPrefix()} set to - * true. + * Returns a reactive Publisher emitting all the blobs and prefixes (directories) under the given prefix + * (directory). Directories will have {@link BlobItem#isPrefix()} set to true. * *

* Blob names are returned in lexicographic order. For more information, see the * Azure Docs. * *

- * E.g. listing a container containing a 'foo' folder, which contains blobs 'foo1' and 'foo2', and a blob - * on the root level 'bar', will return the following results when prefix=null: + * E.g. listing a container containing a 'foo' folder, which contains blobs 'foo1' and 'foo2', and a blob on the + * root level 'bar', will return the following results when prefix=null: * *

    - *
  • foo/ (isPrefix = true) - *
  • bar (isPrefix = false) + *
  • foo/ (isPrefix = true) + *
  • bar (isPrefix = false) *
*

* will return the following results when prefix="foo/": * *

    - *
  • foo/foo1 (isPrefix = false) - *
  • foo/foo2 (isPrefix = false) + *
  • foo/foo1 (isPrefix = false) + *
  • foo/foo2 (isPrefix = false) *
* - * @param delimiter - * The delimiter for blob hierarchy, "/" for hierarchy based on directories - * @param options - * {@link ListBlobsOptions} - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. - * - * @return - * A reactive response emitting the prefixes and blobs. + * @param delimiter The delimiter for blob hierarchy, "/" for hierarchy based on directories + * @param options {@link ListBlobsOptions} + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @return A reactive response emitting the prefixes and blobs. */ public Iterable listBlobsHierarchy(String delimiter, ListBlobsOptions options, Duration timeout) { Flux response = containerAsyncClient.listBlobsHierarchy(delimiter, options); @@ -539,14 +479,10 @@ public Iterable listBlobsHierarchy(String delimiter, ListBlobsOptions * Acquires a lease on the blob for write and delete operations. The lease duration must be between 15 to 60 * seconds, or infinite (-1). * - * @param proposedId - * A {@code String} in any valid GUID format. May be null. - * @param duration - * The duration of the lease, in seconds, or negative one (-1) for a lease that - * never expires. A non-infinite lease can be between 15 and 60 seconds. - * - * @return - * The lease ID. + * @param proposedId A {@code String} in any valid GUID format. May be null. + * @param duration The duration of the lease, in seconds, or negative one (-1) for a lease that never expires. A + * non-infinite lease can be between 15 and 60 seconds. + * @return The lease ID. */ public Response acquireLease(String proposedId, int duration) { return this.acquireLease(proposedId, duration, null, null); @@ -556,23 +492,17 @@ public Response acquireLease(String proposedId, int duration) { * Acquires a lease on the blob for write and delete operations. The lease duration must be between 15 to 60 * seconds, or infinite (-1). * - * @param proposedID - * A {@code String} in any valid GUID format. May be null. - * @param duration - * The duration of the lease, in seconds, or negative one (-1) for a lease that - * never expires. A non-infinite lease can be between 15 and 60 seconds. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. - * - * @return - * The lease ID. + * @param proposedID A {@code String} in any valid GUID format. May be null. + * @param duration The duration of the lease, in seconds, or negative one (-1) for a lease that never expires. A + * non-infinite lease can be between 15 and 60 seconds. + * @param modifiedAccessConditions Standard HTTP Access conditions related to the modification of data. ETag and + * LastModifiedTime are used to construct conditions related to when the blob was changed relative to the given + * request. The request will fail if the specified condition is not satisfied. + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @return The lease ID. */ public Response acquireLease(String proposedID, int duration, - ModifiedAccessConditions modifiedAccessConditions, Duration timeout) { + ModifiedAccessConditions modifiedAccessConditions, Duration timeout) { Mono> response = containerAsyncClient .acquireLease(proposedID, duration, modifiedAccessConditions); @@ -582,11 +512,8 @@ public Response acquireLease(String proposedID, int duration, /** * Renews the blob's previously-acquired lease. * - * @param leaseID - * The leaseId of the active lease on the blob. - * - * @return - * The renewed lease ID. + * @param leaseID The leaseId of the active lease on the blob. + * @return The renewed lease ID. */ public Response renewLease(String leaseID) { return this.renewLease(leaseID, null, null); @@ -595,20 +522,15 @@ public Response renewLease(String leaseID) { /** * Renews the blob's previously-acquired lease. * - * @param leaseID - * The leaseId of the active lease on the blob. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. - * - * @return - * The renewed lease ID. + * @param leaseID The leaseId of the active lease on the blob. + * @param modifiedAccessConditions Standard HTTP Access conditions related to the modification of data. ETag and + * LastModifiedTime are used to construct conditions related to when the blob was changed relative to the given + * request. The request will fail if the specified condition is not satisfied. + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @return The renewed lease ID. */ public Response renewLease(String leaseID, ModifiedAccessConditions modifiedAccessConditions, - Duration timeout) { + Duration timeout) { Mono> response = containerAsyncClient .renewLease(leaseID, modifiedAccessConditions); @@ -618,8 +540,7 @@ public Response renewLease(String leaseID, ModifiedAccessConditions modi /** * Releases the blob's previously-acquired lease. * - * @param leaseID - * The leaseId of the active lease on the blob. + * @param leaseID The leaseId of the active lease on the blob. * @return A response containing status code and HTTP headers */ public VoidResponse releaseLease(String leaseID) { @@ -629,18 +550,15 @@ public VoidResponse releaseLease(String leaseID) { /** * Releases the blob's previously-acquired lease. * - * @param leaseID - * The leaseId of the active lease on the blob. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @param leaseID The leaseId of the active lease on the blob. + * @param modifiedAccessConditions Standard HTTP Access conditions related to the modification of data. ETag and + * LastModifiedTime are used to construct conditions related to when the blob was changed relative to the given + * request. The request will fail if the specified condition is not satisfied. + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. * @return A response containing status code and HTTP headers. */ public VoidResponse releaseLease(String leaseID, - ModifiedAccessConditions modifiedAccessConditions, Duration timeout) { + ModifiedAccessConditions modifiedAccessConditions, Duration timeout) { Mono response = containerAsyncClient .releaseLease(leaseID, modifiedAccessConditions); @@ -651,8 +569,7 @@ public VoidResponse releaseLease(String leaseID, * BreakLease breaks the blob's previously-acquired lease (if it exists). Pass the LeaseBreakDefault (-1) constant * to break a fixed-duration lease when it expires or an infinite lease immediately. * - * @return - * The remaining time in the broken lease. + * @return The remaining time in the broken lease. */ public Response breakLease() { return this.breakLease(null, null, null); @@ -662,24 +579,19 @@ public Response breakLease() { * BreakLease breaks the blob's previously-acquired lease (if it exists). Pass the LeaseBreakDefault (-1) constant * to break a fixed-duration lease when it expires or an infinite lease immediately. * - * @param breakPeriodInSeconds - * An optional {@code Integer} representing the proposed duration of seconds that the lease should continue - * before it is broken, between 0 and 60 seconds. This break period is only used if it is shorter than the - * time remaining on the lease. If longer, the time remaining on the lease is used. A new lease will not be - * available before the break period has expired, but the lease may be held for longer than the break - * period. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. - * - * @return - * The remaining time in the broken lease. + * @param breakPeriodInSeconds An optional {@code Integer} representing the proposed duration of seconds that the + * lease should continue before it is broken, between 0 and 60 seconds. This break period is only used if it is + * shorter than the time remaining on the lease. If longer, the time remaining on the lease is used. A new lease + * will not be available before the break period has expired, but the lease may be held for longer than the break + * period. + * @param modifiedAccessConditions Standard HTTP Access conditions related to the modification of data. ETag and + * LastModifiedTime are used to construct conditions related to when the blob was changed relative to the given + * request. The request will fail if the specified condition is not satisfied. + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @return The remaining time in the broken lease. */ public Response breakLease(Integer breakPeriodInSeconds, - ModifiedAccessConditions modifiedAccessConditions, Duration timeout) { + ModifiedAccessConditions modifiedAccessConditions, Duration timeout) { Mono> response = containerAsyncClient .breakLease(breakPeriodInSeconds, modifiedAccessConditions); @@ -689,36 +601,28 @@ public Response breakLease(Integer breakPeriodInSeconds, /** * ChangeLease changes the blob's lease ID. * - * @param leaseId - * The leaseId of the active lease on the blob. - * @param proposedID - * A {@code String} in any valid GUID format. - * - * @return - * The new lease ID. + * @param leaseId The leaseId of the active lease on the blob. + * @param proposedID A {@code String} in any valid GUID format. + * @return The new lease ID. */ public Response changeLease(String leaseId, String proposedID) { return this.changeLease(leaseId, proposedID, null, null); } /** - * ChangeLease changes the blob's lease ID. For more information, see the Azure Docs. - * - * @param leaseId - * The leaseId of the active lease on the blob. - * @param proposedID - * A {@code String} in any valid GUID format. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. + * ChangeLease changes the blob's lease ID. For more information, see the Azure + * Docs. * + * @param leaseId The leaseId of the active lease on the blob. + * @param proposedID A {@code String} in any valid GUID format. + * @param modifiedAccessConditions Standard HTTP Access conditions related to the modification of data. ETag and + * LastModifiedTime are used to construct conditions related to when the blob was changed relative to the given + * request. The request will fail if the specified condition is not satisfied. + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. * @return The new lease ID. */ public Response changeLease(String leaseId, String proposedID, - ModifiedAccessConditions modifiedAccessConditions, Duration timeout) { + ModifiedAccessConditions modifiedAccessConditions, Duration timeout) { Mono> response = containerAsyncClient .changeLease(leaseId, proposedID, modifiedAccessConditions); @@ -729,11 +633,8 @@ public Response changeLease(String leaseId, String proposedID, * Returns the sku name and account kind for the account. For more information, please see the * Azure Docs. * - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. - * - * @return - * The account info. + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @return The account info. */ public Response getAccountInfo(Duration timeout) { Mono> response = containerAsyncClient.getAccountInfo(); @@ -744,20 +645,14 @@ public Response getAccountInfo(Duration timeout) { /** * Generates a user delegation SAS token with the specified parameters * - * @param userDelegationKey - * The {@code UserDelegationKey} user delegation key for the SAS - * @param accountName - * The {@code String} account name for the SAS - * @param permissions - * The {@code ContainerSASPermissions} permission for the SAS - * @param expiryTime - * The {@code OffsetDateTime} expiry time for the SAS - * - * @return - * A string that represents the SAS token + * @param userDelegationKey The {@code UserDelegationKey} user delegation key for the SAS + * @param accountName The {@code String} account name for the SAS + * @param permissions The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS + * @return A string that represents the SAS token */ public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, String accountName, - ContainerSASPermission permissions, OffsetDateTime expiryTime) { + ContainerSASPermission permissions, OffsetDateTime expiryTime) { return this.containerAsyncClient.generateUserDelegationSAS(userDelegationKey, accountName, permissions, expiryTime); } @@ -765,29 +660,19 @@ public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, Str /** * Generates a user delegation SAS token with the specified parameters * - * @param userDelegationKey - * The {@code UserDelegationKey} user delegation key for the SAS - * @param accountName - * The {@code String} account name for the SAS - * @param permissions - * The {@code ContainerSASPermissions} permission for the SAS - * @param expiryTime - * The {@code OffsetDateTime} expiry time for the SAS - * @param startTime - * An optional {@code OffsetDateTime} start time for the SAS - * @param version - * An optional {@code String} version for the SAS - * @param sasProtocol - * An optional {@code SASProtocol} protocol for the SAS - * @param ipRange - * An optional {@code IPRange} ip address range for the SAS - * - * @return - * A string that represents the SAS token + * @param userDelegationKey The {@code UserDelegationKey} user delegation key for the SAS + * @param accountName The {@code String} account name for the SAS + * @param permissions The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS + * @param startTime An optional {@code OffsetDateTime} start time for the SAS + * @param version An optional {@code String} version for the SAS + * @param sasProtocol An optional {@code SASProtocol} protocol for the SAS + * @param ipRange An optional {@code IPRange} ip address range for the SAS + * @return A string that represents the SAS token */ public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, String accountName, - ContainerSASPermission permissions, OffsetDateTime expiryTime, OffsetDateTime startTime, String version, - SASProtocol sasProtocol, IPRange ipRange) { + ContainerSASPermission permissions, OffsetDateTime expiryTime, OffsetDateTime startTime, String version, + SASProtocol sasProtocol, IPRange ipRange) { return this.containerAsyncClient.generateUserDelegationSAS(userDelegationKey, accountName, permissions, expiryTime, startTime, version, sasProtocol, ipRange); } @@ -795,40 +680,25 @@ public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, Str /** * Generates a user delegation SAS token with the specified parameters * - * @param userDelegationKey - * The {@code UserDelegationKey} user delegation key for the SAS - * @param accountName - * The {@code String} account name for the SAS - * @param permissions - * The {@code ContainerSASPermissions} permission for the SAS - * @param expiryTime - * The {@code OffsetDateTime} expiry time for the SAS - * @param startTime - * An optional {@code OffsetDateTime} start time for the SAS - * @param version - * An optional {@code String} version for the SAS - * @param sasProtocol - * An optional {@code SASProtocol} protocol for the SAS - * @param ipRange - * An optional {@code IPRange} ip address range for the SAS - * @param cacheControl - * An optional {@code String} cache-control header for the SAS. - * @param contentDisposition - * An optional {@code String} content-disposition header for the SAS. - * @param contentEncoding - * An optional {@code String} content-encoding header for the SAS. - * @param contentLanguage - * An optional {@code String} content-language header for the SAS. - * @param contentType - * An optional {@code String} content-type header for the SAS. - * - * @return - * A string that represents the SAS token + * @param userDelegationKey The {@code UserDelegationKey} user delegation key for the SAS + * @param accountName The {@code String} account name for the SAS + * @param permissions The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS + * @param startTime An optional {@code OffsetDateTime} start time for the SAS + * @param version An optional {@code String} version for the SAS + * @param sasProtocol An optional {@code SASProtocol} protocol for the SAS + * @param ipRange An optional {@code IPRange} ip address range for the SAS + * @param cacheControl An optional {@code String} cache-control header for the SAS. + * @param contentDisposition An optional {@code String} content-disposition header for the SAS. + * @param contentEncoding An optional {@code String} content-encoding header for the SAS. + * @param contentLanguage An optional {@code String} content-language header for the SAS. + * @param contentType An optional {@code String} content-type header for the SAS. + * @return A string that represents the SAS token */ public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, String accountName, - ContainerSASPermission permissions, OffsetDateTime expiryTime, OffsetDateTime startTime, String version, - SASProtocol sasProtocol, IPRange ipRange, String cacheControl, String contentDisposition, - String contentEncoding, String contentLanguage, String contentType) { + ContainerSASPermission permissions, OffsetDateTime expiryTime, OffsetDateTime startTime, String version, + SASProtocol sasProtocol, IPRange ipRange, String cacheControl, String contentDisposition, + String contentEncoding, String contentLanguage, String contentType) { return this.containerAsyncClient.generateUserDelegationSAS(userDelegationKey, accountName, permissions, expiryTime, startTime, version, sasProtocol, ipRange, cacheControl, contentDisposition, contentEncoding, contentLanguage, contentType); @@ -837,13 +707,9 @@ public String generateUserDelegationSAS(UserDelegationKey userDelegationKey, Str /** * Generates a SAS token with the specified parameters * - * @param permissions - * The {@code ContainerSASPermissions} permission for the SAS - * @param expiryTime - * The {@code OffsetDateTime} expiry time for the SAS - * - * @return - * A string that represents the SAS token + * @param permissions The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS + * @return A string that represents the SAS token */ public String generateSAS(ContainerSASPermission permissions, OffsetDateTime expiryTime) { return this.containerAsyncClient.generateSAS(permissions, expiryTime); @@ -852,11 +718,8 @@ public String generateSAS(ContainerSASPermission permissions, OffsetDateTime exp /** * Generates a SAS token with the specified parameters * - * @param identifier - * The {@code String} name of the access policy on the container this SAS references if any - * - * @return - * A string that represents the SAS token + * @param identifier The {@code String} name of the access policy on the container this SAS references if any + * @return A string that represents the SAS token */ public String generateSAS(String identifier) { return this.containerAsyncClient.generateSAS(identifier); @@ -865,26 +728,17 @@ public String generateSAS(String identifier) { /** * Generates a SAS token with the specified parameters * - * @param identifier - * The {@code String} name of the access policy on the container this SAS references if any - * @param permissions - * The {@code ContainerSASPermissions} permission for the SAS - * @param expiryTime - * The {@code OffsetDateTime} expiry time for the SAS - * @param startTime - * An optional {@code OffsetDateTime} start time for the SAS - * @param version - * An optional {@code String} version for the SAS - * @param sasProtocol - * An optional {@code SASProtocol} protocol for the SAS - * @param ipRange - * An optional {@code IPRange} ip address range for the SAS - * - * @return - * A string that represents the SAS token + * @param identifier The {@code String} name of the access policy on the container this SAS references if any + * @param permissions The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS + * @param startTime An optional {@code OffsetDateTime} start time for the SAS + * @param version An optional {@code String} version for the SAS + * @param sasProtocol An optional {@code SASProtocol} protocol for the SAS + * @param ipRange An optional {@code IPRange} ip address range for the SAS + * @return A string that represents the SAS token */ public String generateSAS(String identifier, ContainerSASPermission permissions, OffsetDateTime expiryTime, - OffsetDateTime startTime, String version, SASProtocol sasProtocol, IPRange ipRange) { + OffsetDateTime startTime, String version, SASProtocol sasProtocol, IPRange ipRange) { return this.containerAsyncClient.generateSAS(identifier, permissions, expiryTime, startTime, version, sasProtocol, ipRange); } @@ -892,37 +746,23 @@ public String generateSAS(String identifier, ContainerSASPermission permissions, /** * Generates a SAS token with the specified parameters * - * @param identifier - * The {@code String} name of the access policy on the container this SAS references if any - * @param permissions - * The {@code ContainerSASPermissions} permission for the SAS - * @param expiryTime - * The {@code OffsetDateTime} expiry time for the SAS - * @param startTime - * An optional {@code OffsetDateTime} start time for the SAS - * @param version - * An optional {@code String} version for the SAS - * @param sasProtocol - * An optional {@code SASProtocol} protocol for the SAS - * @param ipRange - * An optional {@code IPRange} ip address range for the SAS - * @param cacheControl - * An optional {@code String} cache-control header for the SAS. - * @param contentDisposition - * An optional {@code String} content-disposition header for the SAS. - * @param contentEncoding - * An optional {@code String} content-encoding header for the SAS. - * @param contentLanguage - * An optional {@code String} content-language header for the SAS. - * @param contentType - * An optional {@code String} content-type header for the SAS. - * - * @return - * A string that represents the SAS token + * @param identifier The {@code String} name of the access policy on the container this SAS references if any + * @param permissions The {@code ContainerSASPermissions} permission for the SAS + * @param expiryTime The {@code OffsetDateTime} expiry time for the SAS + * @param startTime An optional {@code OffsetDateTime} start time for the SAS + * @param version An optional {@code String} version for the SAS + * @param sasProtocol An optional {@code SASProtocol} protocol for the SAS + * @param ipRange An optional {@code IPRange} ip address range for the SAS + * @param cacheControl An optional {@code String} cache-control header for the SAS. + * @param contentDisposition An optional {@code String} content-disposition header for the SAS. + * @param contentEncoding An optional {@code String} content-encoding header for the SAS. + * @param contentLanguage An optional {@code String} content-language header for the SAS. + * @param contentType An optional {@code String} content-type header for the SAS. + * @return A string that represents the SAS token */ public String generateSAS(String identifier, ContainerSASPermission permissions, OffsetDateTime expiryTime, - OffsetDateTime startTime, String version, SASProtocol sasProtocol, IPRange ipRange, String cacheControl, - String contentDisposition, String contentEncoding, String contentLanguage, String contentType) { + OffsetDateTime startTime, String version, SASProtocol sasProtocol, IPRange ipRange, String cacheControl, + String contentDisposition, String contentEncoding, String contentLanguage, String contentType) { return this.containerAsyncClient.generateSAS(identifier, permissions, expiryTime, startTime, version, sasProtocol, ipRange, cacheControl, contentDisposition, contentEncoding, contentLanguage, contentType); } diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerRawClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerRawClient.java deleted file mode 100644 index 19d10f5444ee5..0000000000000 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerRawClient.java +++ /dev/null @@ -1,652 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.azure.storage.blob; - -import com.azure.core.http.rest.Response; -import com.azure.storage.blob.implementation.AzureBlobStorageImpl; -import com.azure.storage.blob.models.ContainerAccessConditions; -import com.azure.storage.blob.models.ContainerAccessPolicies; -import com.azure.storage.blob.models.ContainersAcquireLeaseResponse; -import com.azure.storage.blob.models.ContainersBreakLeaseResponse; -import com.azure.storage.blob.models.ContainersChangeLeaseResponse; -import com.azure.storage.blob.models.ContainersCreateResponse; -import com.azure.storage.blob.models.ContainersDeleteResponse; -import com.azure.storage.blob.models.ContainersGetAccountInfoResponse; -import com.azure.storage.blob.models.ContainersGetPropertiesResponse; -import com.azure.storage.blob.models.ContainersListBlobFlatSegmentResponse; -import com.azure.storage.blob.models.ContainersListBlobHierarchySegmentResponse; -import com.azure.storage.blob.models.ContainersReleaseLeaseResponse; -import com.azure.storage.blob.models.ContainersRenewLeaseResponse; -import com.azure.storage.blob.models.ContainersSetAccessPolicyResponse; -import com.azure.storage.blob.models.ContainersSetMetadataResponse; -import com.azure.storage.blob.models.LeaseAccessConditions; -import com.azure.storage.blob.models.ListBlobsOptions; -import com.azure.storage.blob.models.Metadata; -import com.azure.storage.blob.models.ModifiedAccessConditions; -import com.azure.storage.blob.models.PublicAccessType; -import com.azure.storage.blob.models.SignedIdentifier; -import reactor.core.publisher.Mono; - -import java.time.Duration; -import java.util.List; - -/** - * Represents a URL to a container. It may be obtained by direct construction or via the create method on a - * {@link StorageAsyncRawClient} object. This class does not hold any state about a particular blob but is instead a convenient way - * of sending off appropriate requests to the resource on the service. It may also be used to construct URLs to blobs. - * Please refer to the - * Azure Docs - * for more information on containers. - */ -final class ContainerRawClient { - - private ContainerAsyncRawClient containerAsyncRawClient; - - public static final String ROOT_CONTAINER_NAME = "$root"; - - public static final String STATIC_WEBSITE_CONTAINER_NAME = "$web"; - - public static final String LOG_CONTAINER_NAME = "$logs"; - - - /** - * Creates a {@code ContainerAsyncClient} object pointing to the account specified by the URL and using the provided - * pipeline to make HTTP requests. - */ - ContainerRawClient(AzureBlobStorageImpl azureBlobStorage) { - this.containerAsyncRawClient = new ContainerAsyncRawClient(azureBlobStorage); - } - - /** - * Creates a new container within a storage account. If a container with the same name already exists, the operation - * fails. For more information, see the - * Azure Docs. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_basic "Sample code for ContainerAsyncClient.create")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ContainersCreateResponse create() { - return this.create(null, null, null); - } - - /** - * Creates a new container within a storage account. If a container with the same name already exists, the operation - * fails. For more information, see the - * Azure Docs. - * - * @param metadata - * {@link Metadata} - * @param accessType - * Specifies how the data in this container is available to the public. See the x-ms-blob-public-access header - * in the Azure Docs for more information. Pass null for no public access. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_basic "Sample code for ContainerAsyncClient.create")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ContainersCreateResponse create(Metadata metadata, PublicAccessType accessType, Duration timeout) { - Mono response = containerAsyncRawClient.create(metadata, accessType); - return Utility.blockWithOptionalTimeout(response, timeout); - } - - /** - * Marks the specified container for deletion. The container and any blobs contained within it are later - * deleted during garbage collection. For more information, see the - * Azure Docs. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_basic "Sample code for ContainerAsyncClient.delete")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ContainersDeleteResponse delete() { - return this.delete(null, null); - } - - /** - * Marks the specified container for deletion. The container and any blobs contained within it are later - * deleted during garbage collection. For more information, see the - * Azure Docs. - * - * @param accessConditions - * {@link ContainerAccessConditions} - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_basic "Sample code for ContainerAsyncClient.delete")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ContainersDeleteResponse delete(ContainerAccessConditions accessConditions, Duration timeout) { - Mono response = containerAsyncRawClient.delete(accessConditions); - return Utility.blockWithOptionalTimeout(response, timeout); - } - - /** - * Returns the container's metadata and system properties. For more information, see the - * Azure Docs. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_basic "Sample code for ContainerAsyncClient.getProperties")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ContainersGetPropertiesResponse getProperties() { - return this.getProperties(null, null); - } - - /** - * Returns the container's metadata and system properties. For more information, see the - * Azure Docs. - * - * @param leaseAccessConditions - * By setting lease access conditions, requests will fail if the provided lease does not match the active - * lease on the blob. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_basic "Sample code for ContainerAsyncClient.getProperties")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ContainersGetPropertiesResponse getProperties(LeaseAccessConditions leaseAccessConditions, - Duration timeout) { - Mono response = containerAsyncRawClient.getProperties(leaseAccessConditions); - return Utility.blockWithOptionalTimeout(response, timeout); - } - - /** - * Sets the container's metadata. For more information, see the - * Azure Docs. - * - * @param metadata - * {@link Metadata} - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_basic "Sample code for ContainerAsyncClient.setMetadata")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ContainersSetMetadataResponse setMetadata(Metadata metadata) { - return this.setMetadata(metadata, null, null); - } - - /** - * Sets the container's metadata. For more information, see the - * Azure Docs. - * - * @param metadata - * {@link Metadata} - * @param accessConditions - * {@link ContainerAccessConditions} - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_basic "Sample code for ContainerAsyncClient.setMetadata")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ContainersSetMetadataResponse setMetadata(Metadata metadata, - ContainerAccessConditions accessConditions, Duration timeout) { - Mono response = containerAsyncRawClient.setMetadata(metadata, accessConditions); - return Utility.blockWithOptionalTimeout(response, timeout); - } - - /** - * Returns the container's permissions. The permissions indicate whether container's blobs may be accessed publicly. - * For more information, see the - * Azure Docs. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_policy "Sample code for ContainerAsyncClient.getAccessPolicy")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Response getAccessPolicy() { - return this.getAccessPolicy(null, null); - } - - /** - * Returns the container's permissions. The permissions indicate whether container's blobs may be accessed publicly. - * For more information, see the - * Azure Docs. - * - * @param leaseAccessConditions - * By setting lease access conditions, requests will fail if the provided lease does not match the active - * lease on the blob. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_policy "Sample code for ContainerAsyncClient.getAccessPolicy")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Response getAccessPolicy(LeaseAccessConditions leaseAccessConditions, - Duration timeout) { - Mono> response = containerAsyncRawClient.getAccessPolicy(leaseAccessConditions); - return Utility.blockWithOptionalTimeout(response, timeout); - } - - /** - * Sets the container's permissions. The permissions indicate whether blobs in a container may be accessed publicly. - * Note that, for each signed identifier, we will truncate the start and expiry times to the nearest second to - * ensure the time formatting is compatible with the service. For more information, see the - * Azure Docs. - * - * @param accessType - * Specifies how the data in this container is available to the public. See the x-ms-blob-public-access header - * in the Azure Docs for more information. Pass null for no public access. - * @param identifiers - * A list of {@link SignedIdentifier} objects that specify the permissions for the container. Please see - * here - * for more information. Passing null will clear all access policies. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_policy "Sample code for ContainerAsyncClient.setAccessPolicy")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ContainersSetAccessPolicyResponse setAccessPolicy(PublicAccessType accessType, - List identifiers) { - return this.setAccessPolicy(accessType, identifiers, null, null); - } - - /** - * Sets the container's permissions. The permissions indicate whether blobs in a container may be accessed publicly. - * Note that, for each signed identifier, we will truncate the start and expiry times to the nearest second to - * ensure the time formatting is compatible with the service. For more information, see the - * Azure Docs. - * - * @param accessType - * Specifies how the data in this container is available to the public. See the x-ms-blob-public-access header - * in the Azure Docs for more information. Pass null for no public access. - * @param identifiers - * A list of {@link SignedIdentifier} objects that specify the permissions for the container. Please see - * here - * for more information. Passing null will clear all access policies. - * @param accessConditions - * {@link ContainerAccessConditions} - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_policy "Sample code for ContainerAsyncClient.setAccessPolicy")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ContainersSetAccessPolicyResponse setAccessPolicy(PublicAccessType accessType, - List identifiers, ContainerAccessConditions accessConditions, Duration timeout) { - Mono response = containerAsyncRawClient.setAccessPolicy(accessType, identifiers, accessConditions); - return Utility.blockWithOptionalTimeout(response, timeout); - } - - /** - * Acquires a lease on the container for delete operations. The lease duration must be between 15 to - * 60 seconds, or infinite (-1). For more information, see the - * Azure Docs. - * - * @apiNote - * ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_lease "Sample code for ContainerAsyncClient.acquireLease")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/New-Storage-SDK-V10-Preview/src/test/java/com/microsoft/azure/storage/Samples.java) - * - * @param proposedId - * A {@code String} in any valid GUID format. - * @param duration - * The duration of the lease, in seconds, or negative one (-1) for a lease that never expires. - * A non-infinite lease can be between 15 and 60 seconds. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_lease "Sample code for ContainerAsyncClient.acquireLease")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ContainersAcquireLeaseResponse acquireLease(String proposedId, int duration) { - return this.acquireLease(proposedId, duration, null, null); - } - - /** - * Acquires a lease on the container for delete operations. The lease duration must be between 15 to - * 60 seconds, or infinite (-1). For more information, see the - * Azure Docs. - * - * @param proposedID - * A {@code String} in any valid GUID format. - * @param duration - * The duration of the lease, in seconds, or negative one (-1) for a lease that never expires. - * A non-infinite lease can be between 15 and 60 seconds. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_lease "Sample code for ContainerAsyncClient.acquireLease")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ContainersAcquireLeaseResponse acquireLease(String proposedID, int duration, - ModifiedAccessConditions modifiedAccessConditions, Duration timeout) { - Mono response = containerAsyncRawClient.acquireLease(proposedID, duration, modifiedAccessConditions); - return Utility.blockWithOptionalTimeout(response, timeout); - } - - /** - * Renews the container's previously-acquired lease. For more information, see the - * Azure Docs. - * - * @param leaseID - * The leaseId of the active lease on the container. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_lease "Sample code for ContainerAsyncClient.renewLease")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ContainersRenewLeaseResponse renewLease(String leaseID) { - return this.renewLease(leaseID, null, null); - } - - /** - * Renews the container's previously-acquired lease. For more information, see the - * Azure Docs. - * - * @param leaseID - * The leaseId of the active lease on the container. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_lease "Sample code for ContainerAsyncClient.renewLease")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ContainersRenewLeaseResponse renewLease(String leaseID, - ModifiedAccessConditions modifiedAccessConditions, Duration timeout) { - Mono response = containerAsyncRawClient.renewLease(leaseID, modifiedAccessConditions); - return Utility.blockWithOptionalTimeout(response, timeout); - } - - /** - * Releases the container's previously-acquired lease. For more information, see the - * Azure Docs. - * - * @param leaseID - * The leaseId of the active lease on the container. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_lease "Sample code for ContainerAsyncClient.releaseLease")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ContainersReleaseLeaseResponse releaseLease(String leaseID) { - return this.releaseLease(leaseID, null, null); - } - - /** - * Releases the container's previously-acquired lease. For more information, see the - * Azure Docs. - * - * @param leaseID - * The leaseId of the active lease on the container. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_lease "Sample code for ContainerAsyncClient.releaseLease")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ContainersReleaseLeaseResponse releaseLease(String leaseID, - ModifiedAccessConditions modifiedAccessConditions, Duration timeout) { - Mono response = containerAsyncRawClient.releaseLease(leaseID, modifiedAccessConditions); - return Utility.blockWithOptionalTimeout(response, timeout); - } - - /** - * Breaks the container's previously-acquired lease. For more information, see the - * Azure Docs. - * - * @apiNote - * ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_lease "Sample code for ContainerAsyncClient.breakLease")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/New-Storage-SDK-V10-Preview/src/test/java/com/microsoft/azure/storage/Samples.java) - * - * @return Emits the successful response. - */ - public ContainersBreakLeaseResponse breakLease() { - return this.breakLease(null, null, null); - } - - /** - * Breaks the container's previously-acquired lease. For more information, see the - * Azure Docs. - * - * @param breakPeriodInSeconds - * An optional {@code Integer} representing the proposed duration of seconds that the lease should continue - * before it is broken, between 0 and 60 seconds. This break period is only used if it is shorter than the time - * remaining on the lease. If longer, the time remaining on the lease is used. A new lease will not be - * available before the break period has expired, but the lease may be held for longer than the break period. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_lease "Sample code for ContainerAsyncClient.breakLease")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ContainersBreakLeaseResponse breakLease(Integer breakPeriodInSeconds, - ModifiedAccessConditions modifiedAccessConditions, Duration timeout) { - Mono response = containerAsyncRawClient.breakLease(breakPeriodInSeconds, modifiedAccessConditions); - return Utility.blockWithOptionalTimeout(response, timeout); - } - - /** - * Changes the container's leaseAccessConditions. For more information, see the - * Azure Docs. - * - * @param leaseID - * The leaseId of the active lease on the container. - * @param proposedID - * A {@code String} in any valid GUID format. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_lease "Sample code for ContainerAsyncClient.changeLease")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ContainersChangeLeaseResponse changeLease(String leaseID, String proposedID) { - return this.changeLease(leaseID, proposedID, null, null); - } - - /** - * Changes the container's leaseAccessConditions. For more information, see the - * Azure Docs. - * - * @param leaseID - * The leaseId of the active lease on the container. - * @param proposedID - * A {@code String} in any valid GUID format. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=container_lease "Sample code for ContainerAsyncClient.changeLease")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ContainersChangeLeaseResponse changeLease(String leaseID, String proposedID, - ModifiedAccessConditions modifiedAccessConditions, Duration timeout) { - Mono response = containerAsyncRawClient.changeLease(leaseID, proposedID, modifiedAccessConditions); - return Utility.blockWithOptionalTimeout(response, timeout); - } - - /** - * Returns a single segment of blobs starting from the specified Marker. Use an empty - * marker to start enumeration from the beginning. Blob names are returned in lexicographic order. - * After getting a segment, process it, and then call ListBlobs again (passing the the previously-returned - * Marker) to get the next segment. For more information, see the - * Azure Docs. - * - * @param marker - * Identifies the portion of the list to be returned with the next list operation. - * This value is returned in the response of a previous list operation as the - * ListBlobsFlatSegmentResponse.body().nextMarker(). Set to null to list the first segment. - * @param options - * {@link ListBlobsOptions} - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=list_blobs_flat "Sample code for ContainerAsyncClient.listBlobsFlatSegment")] \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=list_blobs_flat_helper "helper code for ContainerAsyncClient.listBlobsFlatSegment")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ContainersListBlobFlatSegmentResponse listBlobsFlatSegment(String marker, ListBlobsOptions options) { - return this.listBlobsFlatSegment(marker, options, null); - } - - /** - * Returns a single segment of blobs starting from the specified Marker. Use an empty - * marker to start enumeration from the beginning. Blob names are returned in lexicographic order. - * After getting a segment, process it, and then call ListBlobs again (passing the the previously-returned - * Marker) to get the next segment. For more information, see the - * Azure Docs. - * - * @param marker - * Identifies the portion of the list to be returned with the next list operation. - * This value is returned in the response of a previous list operation as the - * ListBlobsFlatSegmentResponse.body().nextMarker(). Set to null to list the first segment. - * @param options - * {@link ListBlobsOptions} - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=list_blobs_flat "Sample code for ContainerAsyncClient.listBlobsFlatSegment")] \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=list_blobs_flat_helper "helper code for ContainerAsyncClient.listBlobsFlatSegment")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ContainersListBlobFlatSegmentResponse listBlobsFlatSegment(String marker, ListBlobsOptions options, - Duration timeout) { - Mono response = containerAsyncRawClient.listBlobsFlatSegment(marker, options); - return Utility.blockWithOptionalTimeout(response, timeout); - } - - /** - * Returns a single segment of blobs and blob prefixes starting from the specified Marker. Use an empty - * marker to start enumeration from the beginning. Blob names are returned in lexicographic order. - * After getting a segment, process it, and then call ListBlobs again (passing the the previously-returned - * Marker) to get the next segment. For more information, see the - * Azure Docs. - * - * @param marker - * Identifies the portion of the list to be returned with the next list operation. - * This value is returned in the response of a previous list operation as the - * ListBlobsHierarchySegmentResponse.body().nextMarker(). Set to null to list the first segment. - * @param delimiter - * The operation returns a BlobPrefix element in the response body that acts as a placeholder for all blobs - * whose names begin with the same substring up to the appearance of the delimiter character. The delimiter may - * be a single character or a string. - * @param options - * {@link ListBlobsOptions} - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=list_blobs_hierarchy "Sample code for ContainerAsyncClient.listBlobsHierarchySegment")] \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=list_blobs_hierarchy_helper "helper code for ContainerAsyncClient.listBlobsHierarchySegment")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ContainersListBlobHierarchySegmentResponse listBlobsHierarchySegment(String marker, String delimiter, - ListBlobsOptions options) { - return this.listBlobsHierarchySegment(marker, delimiter, options, null); - } - - /** - * Returns a single segment of blobs and blob prefixes starting from the specified Marker. Use an empty - * marker to start enumeration from the beginning. Blob names are returned in lexicographic order. - * After getting a segment, process it, and then call ListBlobs again (passing the the previously-returned - * Marker) to get the next segment. For more information, see the - * Azure Docs. - * - * @param marker - * Identifies the portion of the list to be returned with the next list operation. - * This value is returned in the response of a previous list operation as the - * ListBlobsHierarchySegmentResponse.body().nextMarker(). Set to null to list the first segment. - * @param delimiter - * The operation returns a BlobPrefix element in the response body that acts as a placeholder for all blobs - * whose names begin with the same substring up to the appearance of the delimiter character. The delimiter may - * be a single character or a string. - * @param options - * {@link ListBlobsOptions} - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=list_blobs_hierarchy "Sample code for ContainerAsyncClient.listBlobsHierarchySegment")] \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=list_blobs_hierarchy_helper "helper code for ContainerAsyncClient.listBlobsHierarchySegment")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ContainersListBlobHierarchySegmentResponse listBlobsHierarchySegment(String marker, String delimiter, - ListBlobsOptions options, Duration timeout) { - Mono response = containerAsyncRawClient.listBlobsHierarchySegment(marker, delimiter, options); - return Utility.blockWithOptionalTimeout(response, timeout); - } - - /** - * Returns the sku name and account kind for the account. For more information, please see the - * Azure Docs. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=account_info "Sample code for ContainerAsyncClient.getAccountInfo")] \n - * For more samples, please see the [Samples file] (https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ContainersGetAccountInfoResponse getAccountInfo() { - return this.getAccountInfo(null); - } - - /** - * Returns the sku name and account kind for the account. For more information, please see the - * Azure Docs. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=account_info "Sample code for ContainerAsyncClient.getAccountInfo")] \n - * For more samples, please see the [Samples file] (https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ContainersGetAccountInfoResponse getAccountInfo(Duration timeout) { - Mono response = containerAsyncRawClient.getAccountInfo(); - return Utility.blockWithOptionalTimeout(response, timeout); - } -} diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/PageBlobAsyncClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/PageBlobAsyncClient.java index 073df29744582..72f052fd27573 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/PageBlobAsyncClient.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/PageBlobAsyncClient.java @@ -5,6 +5,8 @@ import com.azure.core.http.rest.Response; import com.azure.core.http.rest.SimpleResponse; +import com.azure.core.implementation.http.UrlBuilder; +import com.azure.core.util.Context; import com.azure.storage.blob.implementation.AzureBlobStorageBuilder; import com.azure.storage.blob.models.BlobAccessConditions; import com.azure.storage.blob.models.BlobHTTPHeaders; @@ -17,12 +19,14 @@ import com.azure.storage.blob.models.PageRange; import com.azure.storage.blob.models.SequenceNumberActionType; import com.azure.storage.blob.models.SourceModifiedAccessConditions; -import io.netty.buffer.Unpooled; +import io.netty.buffer.ByteBuf; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import java.net.MalformedURLException; import java.net.URL; -import java.nio.ByteBuffer; + +import static com.azure.storage.blob.Utility.postProcessResponse; /** * Client to a page blob. It may only be instantiated through a {@link PageBlobClientBuilder}, via @@ -48,9 +52,6 @@ * object through {@link Mono#toFuture()}. */ public final class PageBlobAsyncClient extends BlobAsyncClient { - - final PageBlobAsyncRawClient pageBlobAsyncRawClient; - /** * Indicates the number of bytes in a page. */ @@ -67,7 +68,6 @@ public final class PageBlobAsyncClient extends BlobAsyncClient { */ PageBlobAsyncClient(AzureBlobStorageBuilder azureBlobStorageBuilder, String snapshot) { super(azureBlobStorageBuilder, snapshot); - this.pageBlobAsyncRawClient = new PageBlobAsyncRawClient(azureBlobStorageBuilder.build(), snapshot); } /** @@ -104,13 +104,30 @@ public Mono> create(long size) { * @param accessConditions * {@link BlobAccessConditions} * - * @return - * A reactive response containing the information of the created page blob. + * @return A reactive response containing the information of the created page blob. + * @throws IllegalArgumentException If {@code size} isn't a multiple of {@link PageBlobAsyncClient#PAGE_BYTES} + * or {@code sequenceNumber} isn't null and is less than 0. */ public Mono> create(long size, Long sequenceNumber, BlobHTTPHeaders headers, Metadata metadata, BlobAccessConditions accessConditions) { - return pageBlobAsyncRawClient - .create(size, sequenceNumber, headers, metadata, accessConditions) + accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions; + + if (size % PAGE_BYTES != 0) { + // Throwing is preferred to Single.error because this will error out immediately instead of waiting until + // subscription. + throw new IllegalArgumentException("size must be a multiple of PageBlobAsyncClient.PAGE_BYTES."); + } + if (sequenceNumber != null && sequenceNumber < 0) { + // Throwing is preferred to Single.error because this will error out immediately instead of waiting until + // subscription. + throw new IllegalArgumentException("SequenceNumber must be greater than or equal to 0."); + } + metadata = metadata == null ? new Metadata() : metadata; + + return postProcessResponse(this.azureBlobStorage.pageBlobs().createWithRestResponseAsync(null, + null, 0, size, null, metadata, null, null, + null, sequenceNumber, null, headers, accessConditions.leaseAccessConditions(), + accessConditions.modifiedAccessConditions(), Context.NONE)) .map(rb -> new SimpleResponse<>(rb, new PageBlobItem(rb.deserializedHeaders()))); } @@ -133,7 +150,7 @@ public Mono> create(long size, Long sequenceNumber, BlobH * @return * A reactive response containing the information of the uploaded pages. */ - public Mono> uploadPages(PageRange pageRange, Flux body) { + public Mono> uploadPages(PageRange pageRange, Flux body) { return this.uploadPages(pageRange, body, null); } @@ -155,13 +172,25 @@ public Mono> uploadPages(PageRange pageRange, Flux> uploadPages(PageRange pageRange, Flux body, + public Mono> uploadPages(PageRange pageRange, Flux body, PageBlobAccessConditions pageBlobAccessConditions) { - return pageBlobAsyncRawClient - .uploadPages(pageRange, body.map(Unpooled::wrappedBuffer), pageBlobAccessConditions) + pageBlobAccessConditions = pageBlobAccessConditions == null ? new PageBlobAccessConditions() : pageBlobAccessConditions; + + if (pageRange == null) { + // Throwing is preferred to Single.error because this will error out immediately instead of waiting until + // subscription. + throw new IllegalArgumentException("pageRange cannot be null."); + } + String pageRangeStr = pageRangeToString(pageRange); + + return postProcessResponse(this.azureBlobStorage.pageBlobs().uploadPagesWithRestResponseAsync(null, + null, body, pageRange.end() - pageRange.start() + 1, null, + null, pageRangeStr, null, null, null, null, + pageBlobAccessConditions.leaseAccessConditions(), pageBlobAccessConditions.sequenceNumberAccessConditions(), + pageBlobAccessConditions.modifiedAccessConditions(), Context.NONE)) .map(rb -> new SimpleResponse<>(rb, new PageBlobItem(rb.deserializedHeaders()))); } @@ -218,15 +247,33 @@ public Mono> uploadPagesFromURL(PageRange range, URL sour * @param sourceAccessConditions * {@link SourceModifiedAccessConditions} * - * @return - * A reactive response containing the information of the uploaded pages. + * @return A reactive response containing the information of the uploaded pages. + * @throws IllegalArgumentException If {@code range} is {@code null} */ public Mono> uploadPagesFromURL(PageRange range, URL sourceURL, Long sourceOffset, byte[] sourceContentMD5, PageBlobAccessConditions destAccessConditions, SourceModifiedAccessConditions sourceAccessConditions) { + if (range == null) { + // Throwing is preferred to Single.error because this will error out immediately instead of waiting until + // subscription. + throw new IllegalArgumentException("range cannot be null."); + } + + String rangeString = pageRangeToString(range); - return pageBlobAsyncRawClient - .uploadPagesFromURL(range, sourceURL, sourceOffset, sourceContentMD5, destAccessConditions, sourceAccessConditions) + if (sourceOffset == null) { + sourceOffset = 0L; + } + + String sourceRangeString = pageRangeToString(new PageRange().start(sourceOffset).end(sourceOffset + (range.end() - range.start()))); + + destAccessConditions = destAccessConditions == null ? new PageBlobAccessConditions() : destAccessConditions; + + return postProcessResponse(this.azureBlobStorage.pageBlobs().uploadPagesFromURLWithRestResponseAsync( + null, null, sourceURL, sourceRangeString, 0, rangeString, sourceContentMD5, + null, null, destAccessConditions.leaseAccessConditions(), + destAccessConditions.sequenceNumberAccessConditions(), destAccessConditions.modifiedAccessConditions(), + sourceAccessConditions, Context.NONE)) .map(rb -> new SimpleResponse<>(rb, new PageBlobItem(rb.deserializedHeaders()))); } @@ -259,13 +306,23 @@ public Mono> clearPages(PageRange pageRange) { * @param pageBlobAccessConditions * {@link PageBlobAccessConditions} * - * @return - * A reactive response containing the information of the cleared pages. + * @return A reactive response containing the information of the cleared pages. + * @throws IllegalArgumentException If {@code pageRange} is {@code null} */ public Mono> clearPages(PageRange pageRange, PageBlobAccessConditions pageBlobAccessConditions) { - return pageBlobAsyncRawClient - .clearPages(pageRange, pageBlobAccessConditions) + pageBlobAccessConditions = pageBlobAccessConditions == null ? new PageBlobAccessConditions() : pageBlobAccessConditions; + if (pageRange == null) { + // Throwing is preferred to Single.error because this will error out immediately instead of waiting until + // subscription. + throw new IllegalArgumentException("pageRange cannot be null."); + } + String pageRangeStr = pageRangeToString(pageRange); + + return postProcessResponse(this.azureBlobStorage.pageBlobs().clearPagesWithRestResponseAsync(null, + null, 0, null, pageRangeStr, null, + pageBlobAccessConditions.leaseAccessConditions(), pageBlobAccessConditions.sequenceNumberAccessConditions(), + pageBlobAccessConditions.modifiedAccessConditions(), Context.NONE)) .map(rb -> new SimpleResponse<>(rb, new PageBlobItem(rb.deserializedHeaders()))); } @@ -295,10 +352,14 @@ public Flux getPageRanges(BlobRange blobRange) { * @return * A reactive response emitting all the page ranges. */ - public Flux getPageRanges(BlobRange blobRange, - BlobAccessConditions accessConditions) { - return pageBlobAsyncRawClient - .getPageRanges(blobRange, accessConditions) + public Flux getPageRanges(BlobRange blobRange, BlobAccessConditions accessConditions) { + blobRange = blobRange == null ? new BlobRange(0) : blobRange; + accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions; + + return postProcessResponse(this.azureBlobStorage.pageBlobs().getPageRangesWithRestResponseAsync( + null, null, snapshot, null, null, blobRange.toHeaderValue(), + null, accessConditions.leaseAccessConditions(), accessConditions.modifiedAccessConditions(), + Context.NONE)) .flatMapMany(response -> Flux.fromIterable(response.value().pageRange())); } @@ -333,13 +394,21 @@ public Flux getPageRangesDiff(BlobRange blobRange, String prevSnapsho * @param accessConditions * {@link BlobAccessConditions} * - * @return - * A reactive response emitting all the different page ranges. + * @return A reactive response emitting all the different page ranges. + * @throws IllegalArgumentException If {@code prevSnapshot} is {@code null} */ - public Flux getPageRangesDiff(BlobRange blobRange, String prevSnapshot, - BlobAccessConditions accessConditions) { - return pageBlobAsyncRawClient - .getPageRangesDiff(blobRange, prevSnapshot, accessConditions) + public Flux getPageRangesDiff(BlobRange blobRange, String prevSnapshot, BlobAccessConditions accessConditions) { + blobRange = blobRange == null ? new BlobRange(0) : blobRange; + accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions; + + if (prevSnapshot == null) { + throw new IllegalArgumentException("prevSnapshot cannot be null"); + } + + return postProcessResponse(this.azureBlobStorage.pageBlobs().getPageRangesDiffWithRestResponseAsync( + null, null, snapshot, null, null, prevSnapshot, + blobRange.toHeaderValue(), null, accessConditions.leaseAccessConditions(), + accessConditions.modifiedAccessConditions(), Context.NONE)) .flatMapMany(response -> Flux.fromIterable(response.value().pageRange())); } @@ -368,12 +437,20 @@ public Mono> resize(long size) { * @param accessConditions * {@link BlobAccessConditions} * - * @return - * A reactive response emitting the resized page blob. + * @return A reactive response emitting the resized page blob. + * @throws IllegalArgumentException If {@code size} isn't a multiple of {@link PageBlobAsyncClient#PAGE_BYTES} */ public Mono> resize(long size, BlobAccessConditions accessConditions) { - return pageBlobAsyncRawClient - .resize(size, accessConditions) + if (size % PAGE_BYTES != 0) { + // Throwing is preferred to Single.error because this will error out immediately instead of waiting until + // subscription. + throw new IllegalArgumentException("size must be a multiple of PageBlobAsyncClient.PAGE_BYTES."); + } + accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions; + + return postProcessResponse(this.azureBlobStorage.pageBlobs().resizeWithRestResponseAsync(null, + null, size, null, null, accessConditions.leaseAccessConditions(), + accessConditions.modifiedAccessConditions(), Context.NONE)) .map(rb -> new SimpleResponse<>(rb, new PageBlobItem(rb.deserializedHeaders()))); } @@ -407,13 +484,22 @@ public Mono> updateSequenceNumber(SequenceNumberActionTyp * @param accessConditions * {@link BlobAccessConditions} * - * @return - * A reactive response emitting the updated page blob. + * @return A reactive response emitting the updated page blob. + * @throws IllegalArgumentException If {@code sequenceNumber} isn't null and is less than 0 */ - public Mono> updateSequenceNumber(SequenceNumberActionType action, - Long sequenceNumber, BlobAccessConditions accessConditions) { - return pageBlobAsyncRawClient - .updateSequenceNumber(action, sequenceNumber, accessConditions) + public Mono> updateSequenceNumber(SequenceNumberActionType action, Long sequenceNumber, BlobAccessConditions accessConditions) { + if (sequenceNumber != null && sequenceNumber < 0) { + // Throwing is preferred to Single.error because this will error out immediately instead of waiting until + // subscription. + throw new IllegalArgumentException("SequenceNumber must be greater than or equal to 0."); + } + accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions; + sequenceNumber = action == SequenceNumberActionType.INCREMENT ? null : sequenceNumber; + + return postProcessResponse( + this.azureBlobStorage.pageBlobs().updateSequenceNumberWithRestResponseAsync(null, + null, action, null, sequenceNumber, null, + accessConditions.leaseAccessConditions(), accessConditions.modifiedAccessConditions(), Context.NONE)) .map(rb -> new SimpleResponse<>(rb, new PageBlobItem(rb.deserializedHeaders()))); } @@ -454,13 +540,37 @@ public Mono> copyIncremental(URL source, String snapsho * to construct conditions related to when the blob was changed relative to the given request. The request * will fail if the specified condition is not satisfied. * - * @return - * A reactive response emitting the copy status. + * @return A reactive response emitting the copy status. + * @throws Error If {@code source} and {@code snapshot} form a malformed URL. */ - public Mono> copyIncremental(URL source, String snapshot, - ModifiedAccessConditions modifiedAccessConditions) { - return pageBlobAsyncRawClient - .copyIncremental(source, snapshot, modifiedAccessConditions) + public Mono> copyIncremental(URL source, String snapshot, ModifiedAccessConditions modifiedAccessConditions) { + UrlBuilder builder = UrlBuilder.parse(source); + builder.setQueryParameter(Constants.SNAPSHOT_QUERY_PARAMETER, snapshot); + try { + source = builder.toURL(); + } catch (MalformedURLException e) { + // We are parsing a valid url and adding a query parameter. If this fails, we can't recover. + throw new Error(e); + } + return postProcessResponse(this.azureBlobStorage.pageBlobs().copyIncrementalWithRestResponseAsync( + null, null, source, null, null, modifiedAccessConditions, Context.NONE)) .map(rb -> new SimpleResponse<>(rb, rb.deserializedHeaders().copyStatus())); } + + private static String pageRangeToString(PageRange pageRange) { + if (pageRange.start() < 0 || pageRange.end() <= 0) { + throw new IllegalArgumentException("PageRange's start and end values must be greater than or equal to " + + "0 if specified."); + } + if (pageRange.start() % PAGE_BYTES != 0) { + throw new IllegalArgumentException("PageRange's start value must be a multiple of 512."); + } + if (pageRange.end() % PAGE_BYTES != PAGE_BYTES - 1) { + throw new IllegalArgumentException("PageRange's end value must be 1 less than a multiple of 512."); + } + if (pageRange.end() <= pageRange.start()) { + throw new IllegalArgumentException("PageRange's End value must be after the start."); + } + return "bytes=" + pageRange.start() + '-' + pageRange.end(); + } } diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/PageBlobAsyncRawClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/PageBlobAsyncRawClient.java deleted file mode 100644 index fba55bd8d7455..0000000000000 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/PageBlobAsyncRawClient.java +++ /dev/null @@ -1,620 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.azure.storage.blob; - -import com.azure.core.implementation.http.UrlBuilder; -import com.azure.core.util.Context; -import com.azure.storage.blob.implementation.AzureBlobStorageImpl; -import com.azure.storage.blob.models.BlobAccessConditions; -import com.azure.storage.blob.models.BlobHTTPHeaders; -import com.azure.storage.blob.models.BlobRange; -import com.azure.storage.blob.models.Metadata; -import com.azure.storage.blob.models.ModifiedAccessConditions; -import com.azure.storage.blob.models.PageBlobAccessConditions; -import com.azure.storage.blob.models.PageBlobsClearPagesResponse; -import com.azure.storage.blob.models.PageBlobsCopyIncrementalResponse; -import com.azure.storage.blob.models.PageBlobsCreateResponse; -import com.azure.storage.blob.models.PageBlobsGetPageRangesDiffResponse; -import com.azure.storage.blob.models.PageBlobsGetPageRangesResponse; -import com.azure.storage.blob.models.PageBlobsResizeResponse; -import com.azure.storage.blob.models.PageBlobsUpdateSequenceNumberResponse; -import com.azure.storage.blob.models.PageBlobsUploadPagesFromURLResponse; -import com.azure.storage.blob.models.PageBlobsUploadPagesResponse; -import com.azure.storage.blob.models.PageRange; -import com.azure.storage.blob.models.SequenceNumberActionType; -import com.azure.storage.blob.models.SourceModifiedAccessConditions; -import io.netty.buffer.ByteBuf; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import java.net.MalformedURLException; -import java.net.URL; - -import static com.azure.storage.blob.Utility.postProcessResponse; - -/** - * Represents a URL to a page blob. It may be obtained by direct construction or via the create method on a - * {@link ContainerAsyncClient} object. This class does not hold any state about a particular blob but is instead a convenient - * way of sending off appropriate requests to the resource on the service. Please refer to the - * Azure Docs - * for more information. - */ -final class PageBlobAsyncRawClient extends BlobAsyncRawClient { - - /** - * Indicates the number of bytes in a page. - */ - public static final int PAGE_BYTES = 512; - - /** - * Indicates the maximum number of bytes that may be sent in a call to putPage. - */ - public static final int MAX_PUT_PAGES_BYTES = 4 * Constants.MB; - - /** - * Creates a {@code PageBlobAsyncRawClient} object pointing to the account specified by the URL and using the provided - * pipeline to make HTTP requests. - * - */ - PageBlobAsyncRawClient(AzureBlobStorageImpl azureBlobStorage, String snapshot) { - super(azureBlobStorage, snapshot); - } - - private static String pageRangeToString(PageRange pageRange) { - if (pageRange.start() < 0 || pageRange.end() <= 0) { - throw new IllegalArgumentException("PageRange's start and end values must be greater than or equal to " - + "0 if specified."); - } - if (pageRange.start() % PageBlobAsyncRawClient.PAGE_BYTES != 0) { - throw new IllegalArgumentException("PageRange's start value must be a multiple of 512."); - } - if (pageRange.end() % PageBlobAsyncRawClient.PAGE_BYTES != PageBlobAsyncRawClient.PAGE_BYTES - 1) { - throw new IllegalArgumentException("PageRange's end value must be 1 less than a multiple of 512."); - } - if (pageRange.end() <= pageRange.start()) { - throw new IllegalArgumentException("PageRange's End value must be after the start."); - } - return new StringBuilder("bytes=").append(pageRange.start()).append('-').append(pageRange.end()).toString(); - } - - /** - * Creates a page blob of the specified length. Call PutPage to upload data data to a page blob. - * For more information, see the - * Azure Docs. - * - * @param size - * Specifies the maximum size for the page blob, up to 8 TB. The page blob size must be aligned to a - * 512-byte boundary. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=page_blob_basic "Sample code for PageBlobAsyncRawClient.create")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono create(long size) { - return this.create(size, null, null, null, null); - } - - /** - * Creates a page blob of the specified length. Call PutPage to upload data data to a page blob. - * For more information, see the - * Azure Docs. - * - * @param size - * Specifies the maximum size for the page blob, up to 8 TB. The page blob size must be aligned to a - * 512-byte boundary. - * @param sequenceNumber - * A user-controlled value that you can use to track requests. The value of the sequence number must be - * between 0 and 2^63 - 1.The default value is 0. - * @param headers - * {@link BlobHTTPHeaders} - * @param metadata - * {@link Metadata} - * @param accessConditions - * {@link BlobAccessConditions} - * - * @return Emits the successful response. - * @throws IllegalArgumentException If {@code size} isn't a multiple of {@link PageBlobAsyncRawClient#PAGE_BYTES} - * or {@code sequenceNumber} isn't null and is less than 0. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=page_blob_basic "Sample code for PageBlobAsyncRawClient.create")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono create(long size, Long sequenceNumber, BlobHTTPHeaders headers, - Metadata metadata, BlobAccessConditions accessConditions) { - accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions; - - if (size % PageBlobAsyncRawClient.PAGE_BYTES != 0) { - // Throwing is preferred to Single.error because this will error out immediately instead of waiting until - // subscription. - throw new IllegalArgumentException("size must be a multiple of PageBlobAsyncRawClient.PAGE_BYTES."); - } - if (sequenceNumber != null && sequenceNumber < 0) { - // Throwing is preferred to Single.error because this will error out immediately instead of waiting until - // subscription. - throw new IllegalArgumentException("SequenceNumber must be greater than or equal to 0."); - } - metadata = metadata == null ? new Metadata() : metadata; - - return postProcessResponse(this.azureBlobStorage.pageBlobs().createWithRestResponseAsync(null, - null, 0, size, null, metadata, null, null, - null, sequenceNumber, null, headers, accessConditions.leaseAccessConditions(), - accessConditions.modifiedAccessConditions(), Context.NONE)); - } - - /** - * Writes 1 or more pages to the page blob. The start and end offsets must be a multiple of 512. - * For more information, see the - * Azure Docs. - *

- * Note that the data passed must be replayable if retries are enabled (the default). In other words, the - * {@code Flux} must produce the same data each time it is subscribed to. - * - * @param pageRange - * A {@link PageRange} object. Given that pages must be aligned with 512-byte boundaries, the start offset must - * be a modulus of 512 and the end offset must be a modulus of 512 - 1. Examples of valid byte ranges are - * 0-511, 512-1023, etc. - * @param body - * The data to upload. Note that this {@code Flux} must be replayable if retries are enabled - * (the default). In other words, the Flowable must produce the same data each time it is subscribed to. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=page_blob_basic "Sample code for PageBlobAsyncRawClient.uploadPages")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono uploadPages(PageRange pageRange, Flux body) { - return this.uploadPages(pageRange, body, null); - } - - /** - * Writes 1 or more pages to the page blob. The start and end offsets must be a multiple of 512. - * For more information, see the - * Azure Docs. - *

- * Note that the data passed must be replayable if retries are enabled (the default). In other words, the - * {@code Flux} must produce the same data each time it is subscribed to. - * - * @param pageRange - * A {@link PageRange} object. Given that pages must be aligned with 512-byte boundaries, the start offset - * must be a modulus of 512 and the end offset must be a modulus of 512 - 1. Examples of valid byte ranges - * are 0-511, 512-1023, etc. - * @param body - * The data to upload. Note that this {@code Flux} must be replayable if retries are enabled - * (the default). In other words, the Flowable must produce the same data each time it is subscribed to. - * @param pageBlobAccessConditions - * {@link PageBlobAccessConditions} - * - * @return Emits the successful response. - * @throws IllegalArgumentException If {@code pageRange} is {@code null} - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=page_blob_basic "Sample code for PageBlobAsyncRawClient.uploadPages")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono uploadPages(PageRange pageRange, Flux body, - PageBlobAccessConditions pageBlobAccessConditions) { - pageBlobAccessConditions = pageBlobAccessConditions == null ? new PageBlobAccessConditions() - : pageBlobAccessConditions; - - if (pageRange == null) { - // Throwing is preferred to Single.error because this will error out immediately instead of waiting until - // subscription. - throw new IllegalArgumentException("pageRange cannot be null."); - } - String pageRangeStr = pageRangeToString(pageRange); - - return postProcessResponse(this.azureBlobStorage.pageBlobs().uploadPagesWithRestResponseAsync(null, - null, body, pageRange.end() - pageRange.start() + 1, null, - null, pageRangeStr, null, null, null, null, - pageBlobAccessConditions.leaseAccessConditions(), pageBlobAccessConditions.sequenceNumberAccessConditions(), - pageBlobAccessConditions.modifiedAccessConditions(), Context.NONE)); - } - - /** - * Writes 1 or more pages from the source page blob to this page blob. The start and end offsets must be a multiple - * of 512. - * For more information, see the - * Azure Docs. - *

- * - * @param range - * A {@link PageRange} object. Given that pages must be aligned with 512-byte boundaries, the start offset - * must be a modulus of 512 and the end offset must be a modulus of 512 - 1. Examples of valid byte ranges - * are 0-511, 512-1023, etc. - * @param sourceURL - * The url to the blob that will be the source of the copy. A source blob in the same storage account can be - * authenticated via Shared Key. However, if the source is a blob in another account, the source blob must - * either be public or must be authenticated via a shared access signature. If the source blob is public, no - * authentication is required to perform the operation. - * @param sourceOffset - * The source offset to copy from. Pass null or 0 to copy from the beginning of source page blob. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=page_from_url "Sample code for PageBlobAsyncRawClient.uploadPagesFromURL")] - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono uploadPagesFromURL(PageRange range, URL sourceURL, Long sourceOffset) { - return this.uploadPagesFromURL(range, sourceURL, sourceOffset, null, null, - null); - } - - /** - * Writes 1 or more pages from the source page blob to this page blob. The start and end offsets must be a multiple - * of 512. - * For more information, see the - * Azure Docs. - *

- * - * @param range - * The destination {@link PageRange} range. Given that pages must be aligned with 512-byte boundaries, the start offset - * must be a modulus of 512 and the end offset must be a modulus of 512 - 1. Examples of valid byte ranges - * are 0-511, 512-1023, etc. - * @param sourceURL - * The url to the blob that will be the source of the copy. A source blob in the same storage account can be - * authenticated via Shared Key. However, if the source is a blob in another account, the source blob must - * either be public or must be authenticated via a shared access signature. If the source blob is public, no - * authentication is required to perform the operation. - * @param sourceOffset - * The source offset to copy from. Pass null or 0 to copy from the beginning of source blob. - * @param sourceContentMD5 - * An MD5 hash of the block content from the source blob. If specified, the service will calculate the MD5 - * of the received data and fail the request if it does not match the provided MD5. - * @param destAccessConditions - * {@link PageBlobAccessConditions} - * @param sourceAccessConditions - * {@link SourceModifiedAccessConditions} - * - * @return Emits the successful response. - * @throws IllegalArgumentException If {@code range} is {@code null} - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=page_from_url "Sample code for PageBlobAsyncRawClient.uploadPagesFromURL")] - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono uploadPagesFromURL(PageRange range, URL sourceURL, Long sourceOffset, - byte[] sourceContentMD5, PageBlobAccessConditions destAccessConditions, - SourceModifiedAccessConditions sourceAccessConditions) { - - if (range == null) { - // Throwing is preferred to Single.error because this will error out immediately instead of waiting until - // subscription. - throw new IllegalArgumentException("range cannot be null."); - } - - String rangeString = pageRangeToString(range); - - if (sourceOffset == null) { - sourceOffset = 0L; - } - - String sourceRangeString = pageRangeToString(new PageRange().start(sourceOffset).end(sourceOffset + (range.end() - range.start()))); - - destAccessConditions = destAccessConditions == null ? new PageBlobAccessConditions() : destAccessConditions; - - return postProcessResponse(this.azureBlobStorage.pageBlobs().uploadPagesFromURLWithRestResponseAsync( - null, null, sourceURL, sourceRangeString, 0, rangeString, sourceContentMD5, - null, null, destAccessConditions.leaseAccessConditions(), - destAccessConditions.sequenceNumberAccessConditions(), destAccessConditions.modifiedAccessConditions(), - sourceAccessConditions, Context.NONE)); - } - - /** - * Frees the specified pages from the page blob. - * For more information, see the - * Azure Docs. - * - * @param pageRange - * A {@link PageRange} object. Given that pages must be aligned with 512-byte boundaries, the start offset - * must be a modulus of 512 and the end offset must be a modulus of 512 - 1. Examples of valid byte ranges - * are 0-511, 512-1023, etc. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=page_blob_basic "Sample code for PageBlobAsyncRawClient.clearPages")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono clearPages(PageRange pageRange) { - return this.clearPages(pageRange, null); - } - - /** - * Frees the specified pages from the page blob. - * For more information, see the - * Azure Docs. - * - * @param pageRange - * A {@link PageRange} object. Given that pages must be aligned with 512-byte boundaries, the start offset - * must be a modulus of 512 and the end offset must be a modulus of 512 - 1. Examples of valid byte ranges - * are 0-511, 512-1023, etc. - * @param pageBlobAccessConditions - * {@link PageBlobAccessConditions} - * - * @return Emits the successful response. - * @throws IllegalArgumentException If {@code pageRange} is {@code null} - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=page_blob_basic "Sample code for PageBlobAsyncRawClient.clearPages")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono clearPages(PageRange pageRange, - PageBlobAccessConditions pageBlobAccessConditions) { - pageBlobAccessConditions = pageBlobAccessConditions == null ? new PageBlobAccessConditions() - : pageBlobAccessConditions; - if (pageRange == null) { - // Throwing is preferred to Single.error because this will error out immediately instead of waiting until - // subscription. - throw new IllegalArgumentException("pageRange cannot be null."); - } - String pageRangeStr = pageRangeToString(pageRange); - - return postProcessResponse(this.azureBlobStorage.pageBlobs().clearPagesWithRestResponseAsync(null, - null, 0, null, pageRangeStr, null, - pageBlobAccessConditions.leaseAccessConditions(), pageBlobAccessConditions.sequenceNumberAccessConditions(), - pageBlobAccessConditions.modifiedAccessConditions(), Context.NONE)); - } - - /** - * Returns the list of valid page ranges for a page blob or snapshot of a page blob. - * For more information, see the Azure Docs. - * - * @param blobRange - * {@link BlobRange} - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=page_blob_basic "Sample code for PageBlobAsyncRawClient.getPageRanges")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono getPageRanges(BlobRange blobRange) { - return this.getPageRanges(blobRange, null); - } - - /** - * Returns the list of valid page ranges for a page blob or snapshot of a page blob. - * For more information, see the Azure Docs. - * - * @param blobRange - * {@link BlobRange} - * @param accessConditions - * {@link BlobAccessConditions} - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=page_blob_basic "Sample code for PageBlobAsyncRawClient.getPageRanges")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono getPageRanges(BlobRange blobRange, - BlobAccessConditions accessConditions) { - blobRange = blobRange == null ? new BlobRange(0) : blobRange; - accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions; - - return postProcessResponse(this.azureBlobStorage.pageBlobs().getPageRangesWithRestResponseAsync( - null, null, snapshot, null, null, blobRange.toHeaderValue(), - null, accessConditions.leaseAccessConditions(), accessConditions.modifiedAccessConditions(), - Context.NONE)); - } - - /** - * Gets the collection of page ranges that differ between a specified snapshot and this page blob. - * For more information, see the Azure Docs. - * - * @param blobRange - * {@link BlobRange} - * @param prevSnapshot - * Specifies that the response will contain only pages that were changed between target blob and previous - * snapshot. Changed pages include both updated and cleared pages. The target - * blob may be a snapshot, as long as the snapshot specified by prevsnapshot is the older of the two. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=page_diff "Sample code for PageBlobAsyncRawClient.getPageRangesDiff")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono getPageRangesDiff(BlobRange blobRange, String prevSnapshot) { - return this.getPageRangesDiff(blobRange, prevSnapshot, null); - } - - /** - * Gets the collection of page ranges that differ between a specified snapshot and this page blob. - * For more information, see the Azure Docs. - * - * @param blobRange - * {@link BlobRange} - * @param prevSnapshot - * Specifies that the response will contain only pages that were changed between target blob and previous - * snapshot. Changed pages include both updated and cleared pages. The target - * blob may be a snapshot, as long as the snapshot specified by prevsnapshot is the older of the two. - * @param accessConditions - * {@link BlobAccessConditions} - * - * @return Emits the successful response. - * @throws IllegalArgumentException If {@code prevSnapshot} is {@code null} - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=page_diff "Sample code for PageBlobAsyncRawClient.getPageRangesDiff")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono getPageRangesDiff(BlobRange blobRange, String prevSnapshot, - BlobAccessConditions accessConditions) { - blobRange = blobRange == null ? new BlobRange(0) : blobRange; - accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions; - - if (prevSnapshot == null) { - throw new IllegalArgumentException("prevSnapshot cannot be null"); - } - - return postProcessResponse(this.azureBlobStorage.pageBlobs().getPageRangesDiffWithRestResponseAsync( - null, null, snapshot, null, null, prevSnapshot, - blobRange.toHeaderValue(), null, accessConditions.leaseAccessConditions(), - accessConditions.modifiedAccessConditions(), Context.NONE)); - } - - /** - * Resizes the page blob to the specified size (which must be a multiple of 512). - * For more information, see the Azure Docs. - * - * @param size - * Resizes a page blob to the specified size. If the specified value is less than the current size of the - * blob, then all pages above the specified value are cleared. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=page_blob_basic "Sample code for PageBlobAsyncRawClient.resize")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono resize(long size) { - return this.resize(size, null); - } - - /** - * Resizes the page blob to the specified size (which must be a multiple of 512). - * For more information, see the Azure Docs. - * - * @param size - * Resizes a page blob to the specified size. If the specified value is less than the current size of the - * blob, then all pages above the specified value are cleared. - * @param accessConditions - * {@link BlobAccessConditions} - * - * @return Emits the successful response. - * @throws IllegalArgumentException If {@code size} isn't a multiple of {@link PageBlobAsyncRawClient#PAGE_BYTES} - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=page_blob_basic "Sample code for PageBlobAsyncRawClient.resize")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono resize(long size, BlobAccessConditions accessConditions) { - if (size % PageBlobAsyncRawClient.PAGE_BYTES != 0) { - // Throwing is preferred to Single.error because this will error out immediately instead of waiting until - // subscription. - throw new IllegalArgumentException("size must be a multiple of PageBlobAsyncRawClient.PAGE_BYTES."); - } - accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions; - - return postProcessResponse(this.azureBlobStorage.pageBlobs().resizeWithRestResponseAsync(null, - null, size, null, null, accessConditions.leaseAccessConditions(), - accessConditions.modifiedAccessConditions(), Context.NONE)); - } - - /** - * Sets the page blob's sequence number. - * For more information, see the Azure Docs. - * - * @param action - * Indicates how the service should modify the blob's sequence number. - * @param sequenceNumber - * The blob's sequence number. The sequence number is a user-controlled property that you can use to track - * requests and manage concurrency issues. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=page_blob_basic "Sample code for PageBlobAsyncRawClient.updateSequenceNumber")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono updateSequenceNumber(SequenceNumberActionType action, - Long sequenceNumber) { - return this.updateSequenceNumber(action, sequenceNumber, null); - } - - /** - * Sets the page blob's sequence number. - * For more information, see the Azure Docs. - * - * @param action - * Indicates how the service should modify the blob's sequence number. - * @param sequenceNumber - * The blob's sequence number. The sequence number is a user-controlled property that you can use to track - * requests and manage concurrency issues. - * @param accessConditions - * {@link BlobAccessConditions} - * - * @return Emits the successful response. - * @throws IllegalArgumentException If {@code sequenceNumber} isn't null and is less than 0 - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=page_blob_basic "Sample code for PageBlobAsyncRawClient.updateSequenceNumber")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono updateSequenceNumber(SequenceNumberActionType action, - Long sequenceNumber, BlobAccessConditions accessConditions) { - if (sequenceNumber != null && sequenceNumber < 0) { - // Throwing is preferred to Single.error because this will error out immediately instead of waiting until - // subscription. - throw new IllegalArgumentException("SequenceNumber must be greater than or equal to 0."); - } - accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions; - sequenceNumber = action == SequenceNumberActionType.INCREMENT ? null : sequenceNumber; - - return postProcessResponse( - this.azureBlobStorage.pageBlobs().updateSequenceNumberWithRestResponseAsync(null, - null, action, null, sequenceNumber, null, - accessConditions.leaseAccessConditions(), accessConditions.modifiedAccessConditions(), Context.NONE)); - } - - /** - * Begins an operation to start an incremental copy from one page blob's snapshot to this page - * blob. The snapshot is copied such that only the differential changes between the previously copied snapshot are - * transferred to the destination. The copied snapshots are complete copies of the original snapshot and can be read - * or copied from as usual. For more information, see - * the Azure Docs here and - * here. - * - * @param source - * The source page blob. - * @param snapshot - * The snapshot on the copy source. - * - * @return Emits the successful response. - */ - public Mono copyIncremental(URL source, String snapshot) { - return this.copyIncremental(source, snapshot, null); - } - - /** - * Begins an operation to start an incremental copy from one page blob's snapshot to this page - * blob. The snapshot is copied such that only the differential changes between the previously copied snapshot are - * transferred to the destination. The copied snapshots are complete copies of the original snapshot and can be read - * or copied from as usual. For more information, see - * the Azure Docs here and - * here. - * - * @param source - * The source page blob. - * @param snapshot - * The snapshot on the copy source. - * @param modifiedAccessConditions - * Standard HTTP Access conditions related to the modification of data. ETag and LastModifiedTime are used - * to construct conditions related to when the blob was changed relative to the given request. The request - * will fail if the specified condition is not satisfied. - * - * @return Emits the successful response. - * @throws Error If {@code source} and {@code snapshot} form a malformed URL. - */ - public Mono copyIncremental(URL source, String snapshot, - ModifiedAccessConditions modifiedAccessConditions) { - - UrlBuilder builder = UrlBuilder.parse(source); - builder.setQueryParameter(Constants.SNAPSHOT_QUERY_PARAMETER, snapshot); - try { - source = builder.toURL(); - } catch (MalformedURLException e) { - // We are parsing a valid url and adding a query parameter. If this fails, we can't recover. - throw new Error(e); - } - return postProcessResponse(this.azureBlobStorage.pageBlobs().copyIncrementalWithRestResponseAsync( - null, null, source, null, null, modifiedAccessConditions, Context.NONE)); - } -} diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/PageBlobClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/PageBlobClient.java index 284f74d0216ac..62d2146ea8d61 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/PageBlobClient.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/PageBlobClient.java @@ -15,13 +15,14 @@ import com.azure.storage.blob.models.PageRange; import com.azure.storage.blob.models.SequenceNumberActionType; import com.azure.storage.blob.models.SourceModifiedAccessConditions; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.core.scheduler.Schedulers; import java.io.InputStream; import java.net.URL; -import java.nio.ByteBuffer; import java.time.Duration; /** @@ -45,12 +46,12 @@ public final class PageBlobClient extends BlobClient { /** * Indicates the number of bytes in a page. */ - public static final int PAGE_BYTES = 512; + public static final int PAGE_BYTES = PageBlobAsyncClient.PAGE_BYTES; /** * Indicates the maximum number of bytes that may be sent in a call to putPage. */ - public static final int MAX_PUT_PAGES_BYTES = 4 * Constants.MB; + public static final int MAX_PUT_PAGES_BYTES = PageBlobAsyncClient.MAX_PUT_PAGES_BYTES; /** * Package-private constructor for use by {@link PageBlobClientBuilder}. @@ -189,7 +190,7 @@ public Response uploadPages(PageRange pageRange, InputStream body) public Response uploadPages(PageRange pageRange, InputStream body, PageBlobAccessConditions pageBlobAccessConditions, Duration timeout) { long length = pageRange.end() - pageRange.start(); - Flux fbb = Flux.range(0, (int) Math.ceil((double) length / (double) PAGE_BYTES)) + Flux fbb = Flux.range(0, (int) Math.ceil((double) length / (double) PAGE_BYTES)) .map(i -> i * PAGE_BYTES) .concatMap(pos -> Mono.fromCallable(() -> { byte[] cache = new byte[PAGE_BYTES]; @@ -197,7 +198,8 @@ public Response uploadPages(PageRange pageRange, InputStream body, while (read < PAGE_BYTES) { read += body.read(cache, read, PAGE_BYTES - read); } - return ByteBuffer.wrap(cache); + + return ByteBufAllocator.DEFAULT.buffer(read).writeBytes(cache); })); Mono> response = pageBlobAsyncClient.uploadPages(pageRange, diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/ServiceSASSignatureValues.java b/storage/client/blob/src/main/java/com/azure/storage/blob/ServiceSASSignatureValues.java index 114c28eb71209..f6b4767cada56 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/ServiceSASSignatureValues.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/ServiceSASSignatureValues.java @@ -12,10 +12,10 @@ import java.time.OffsetDateTime; /** - * ServiceSASSignatureValues is used to generate a Shared Access Signature (SAS) for an Azure Storage service. Once - * all the values here are set appropriately, call generateSASQueryParameters to obtain a representation of the SAS - * which can actually be applied to blob urls. Note: that both this class and {@link SASQueryParameters} exist because - * the former is mutable and a logical representation while the latter is immutable and used to generate actual REST + * ServiceSASSignatureValues is used to generate a Shared Access Signature (SAS) for an Azure Storage service. Once all + * the values here are set appropriately, call generateSASQueryParameters to obtain a representation of the SAS which + * can actually be applied to blob urls. Note: that both this class and {@link SASQueryParameters} exist because the + * former is mutable and a logical representation while the latter is immutable and used to generate actual REST * requests. *

* Please see here @@ -24,9 +24,9 @@ * Please see here for * more details on each value, including which are required. * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=service_sas "Sample code for ServiceSASSignatureValues")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) + * @apiNote ## Sample Code \n [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=service_sas + * "Sample code for ServiceSASSignatureValues")] \n For more samples, please see the [Samples + * file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) */ final class ServiceSASSignatureValues { @@ -68,6 +68,7 @@ final class ServiceSASSignatureValues { /** * Creates an object with the specified expiry time and permissions + * * @param expiryTime * @param permissions */ @@ -78,6 +79,7 @@ final class ServiceSASSignatureValues { /** * Creates an object with the specified identifier + * * @param identifier */ ServiceSASSignatureValues(String identifier) { @@ -85,8 +87,8 @@ final class ServiceSASSignatureValues { } ServiceSASSignatureValues(String version, SASProtocol sasProtocol, OffsetDateTime startTime, - OffsetDateTime expiryTime, String permission, IPRange ipRange, String identifier, String cacheControl, - String contentDisposition, String contentEncoding, String contentLanguage, String contentType) { + OffsetDateTime expiryTime, String permission, IPRange ipRange, String identifier, String cacheControl, + String contentDisposition, String contentEncoding, String contentLanguage, String contentType) { if (version != null) { this.version = version; } @@ -229,6 +231,7 @@ public ServiceSASSignatureValues canonicalName(String canonicalName) { /** * The canonical name of the object the SAS user may access. + * * @throws RuntimeException If urlString is a malformed URL. */ public ServiceSASSignatureValues canonicalName(String urlString, String accountName) { @@ -359,9 +362,7 @@ public ServiceSASSignatureValues contentType(String contentType) { * Uses an account's shared key credential to sign these signature values to produce the proper SAS query * parameters. * - * @param sharedKeyCredentials - * A {@link SharedKeyCredential} object used to sign the SAS values. - * + * @param sharedKeyCredentials A {@link SharedKeyCredential} object used to sign the SAS values. * @return {@link SASQueryParameters} * @throws Error If the accountKey is not a valid Base64-encoded string. */ @@ -380,17 +381,15 @@ public SASQueryParameters generateSASQueryParameters(SharedKeyCredential sharedK } return new SASQueryParameters(this.version, null, null, - this.protocol, this.startTime, this.expiryTime, this.ipRange, this.identifier, resource, - this.permissions, signature, this.cacheControl, this.contentDisposition, this.contentEncoding, - this.contentLanguage, this.contentType, null /* delegate */); + this.protocol, this.startTime, this.expiryTime, this.ipRange, this.identifier, resource, + this.permissions, signature, this.cacheControl, this.contentDisposition, this.contentEncoding, + this.contentLanguage, this.contentType, null /* delegate */); } /** * Uses a user delegation key to sign these signature values to produce the proper SAS query parameters. * - * @param delegationKey - * A {@link UserDelegationKey} object used to sign the SAS values. - * + * @param delegationKey A {@link UserDelegationKey} object used to sign the SAS values. * @return {@link SASQueryParameters} * @throws Error If the accountKey is not a valid Base64-encoded string. */ @@ -409,9 +408,9 @@ public SASQueryParameters generateSASQueryParameters(UserDelegationKey delegatio } return new SASQueryParameters(this.version, null, null, - this.protocol, this.startTime, this.expiryTime, this.ipRange, null /* identifier */, resource, - this.permissions, signature, this.cacheControl, this.contentDisposition, this.contentEncoding, - this.contentLanguage, this.contentType, delegationKey); + this.protocol, this.startTime, this.expiryTime, this.ipRange, null /* identifier */, resource, + this.permissions, signature, this.cacheControl, this.contentDisposition, this.contentEncoding, + this.contentLanguage, this.contentType, delegationKey); } /** @@ -441,46 +440,46 @@ private void assertGenerateOK(boolean usingUserDelegation) { private String stringToSign() { return String.join("\n", - this.permissions == null ? "" : this.permissions, - this.startTime == null ? "" : Utility.ISO_8601_UTC_DATE_FORMATTER.format(this.startTime), - this.expiryTime == null ? "" : Utility.ISO_8601_UTC_DATE_FORMATTER.format(this.expiryTime), - this.canonicalName == null ? "" : this.canonicalName, - this.identifier == null ? "" : this.identifier, - this.ipRange == null ? (new IPRange()).toString() : this.ipRange.toString(), - this.protocol == null ? "" : protocol.toString(), - this.version == null ? "" : this.version, - this.resource == null ? "" : this.resource, - this.snapshotId == null ? "" : this.snapshotId, - this.cacheControl == null ? "" : this.cacheControl, - this.contentDisposition == null ? "" : this.contentDisposition, - this.contentEncoding == null ? "" : this.contentEncoding, - this.contentLanguage == null ? "" : this.contentLanguage, - this.contentType == null ? "" : this.contentType + this.permissions == null ? "" : this.permissions, + this.startTime == null ? "" : Utility.ISO_8601_UTC_DATE_FORMATTER.format(this.startTime), + this.expiryTime == null ? "" : Utility.ISO_8601_UTC_DATE_FORMATTER.format(this.expiryTime), + this.canonicalName == null ? "" : this.canonicalName, + this.identifier == null ? "" : this.identifier, + this.ipRange == null ? (new IPRange()).toString() : this.ipRange.toString(), + this.protocol == null ? "" : protocol.toString(), + this.version == null ? "" : this.version, + this.resource == null ? "" : this.resource, + this.snapshotId == null ? "" : this.snapshotId, + this.cacheControl == null ? "" : this.cacheControl, + this.contentDisposition == null ? "" : this.contentDisposition, + this.contentEncoding == null ? "" : this.contentEncoding, + this.contentLanguage == null ? "" : this.contentLanguage, + this.contentType == null ? "" : this.contentType ); } private String stringToSign(final UserDelegationKey key) { return String.join("\n", - this.permissions == null ? "" : this.permissions, - this.startTime == null ? "" : Utility.ISO_8601_UTC_DATE_FORMATTER.format(this.startTime), - this.expiryTime == null ? "" : Utility.ISO_8601_UTC_DATE_FORMATTER.format(this.expiryTime), - this.canonicalName == null ? "" : this.canonicalName, - key.signedOid() == null ? "" : key.signedOid(), - key.signedTid() == null ? "" : key.signedTid(), - key.signedStart() == null ? "" : Utility.ISO_8601_UTC_DATE_FORMATTER.format(key.signedStart()), - key.signedExpiry() == null ? "" : Utility.ISO_8601_UTC_DATE_FORMATTER.format(key.signedExpiry()), - key.signedService() == null ? "" : key.signedService(), - key.signedVersion() == null ? "" : key.signedVersion(), - this.ipRange == null ? new IPRange().toString() : this.ipRange.toString(), - this.protocol == null ? "" : this.protocol.toString(), - this.version == null ? "" : this.version, - this.resource == null ? "" : this.resource, - this.snapshotId == null ? "" : this.snapshotId, - this.cacheControl == null ? "" : this.cacheControl, - this.contentDisposition == null ? "" : this.contentDisposition, - this.contentEncoding == null ? "" : this.contentEncoding, - this.contentLanguage == null ? "" : this.contentLanguage, - this.contentType == null ? "" : this.contentType + this.permissions == null ? "" : this.permissions, + this.startTime == null ? "" : Utility.ISO_8601_UTC_DATE_FORMATTER.format(this.startTime), + this.expiryTime == null ? "" : Utility.ISO_8601_UTC_DATE_FORMATTER.format(this.expiryTime), + this.canonicalName == null ? "" : this.canonicalName, + key.signedOid() == null ? "" : key.signedOid(), + key.signedTid() == null ? "" : key.signedTid(), + key.signedStart() == null ? "" : Utility.ISO_8601_UTC_DATE_FORMATTER.format(key.signedStart()), + key.signedExpiry() == null ? "" : Utility.ISO_8601_UTC_DATE_FORMATTER.format(key.signedExpiry()), + key.signedService() == null ? "" : key.signedService(), + key.signedVersion() == null ? "" : key.signedVersion(), + this.ipRange == null ? new IPRange().toString() : this.ipRange.toString(), + this.protocol == null ? "" : this.protocol.toString(), + this.version == null ? "" : this.version, + this.resource == null ? "" : this.resource, + this.snapshotId == null ? "" : this.snapshotId, + this.cacheControl == null ? "" : this.cacheControl, + this.contentDisposition == null ? "" : this.contentDisposition, + this.contentEncoding == null ? "" : this.contentEncoding, + this.contentLanguage == null ? "" : this.contentLanguage, + this.contentType == null ? "" : this.contentType ); } } diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/StorageAsyncClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/StorageAsyncClient.java index c6c48d7e5770d..b93ee7bd579e7 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/StorageAsyncClient.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/StorageAsyncClient.java @@ -8,8 +8,11 @@ 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.blob.implementation.AzureBlobStorageBuilder; +import com.azure.storage.blob.implementation.AzureBlobStorageImpl; import com.azure.storage.blob.models.ContainerItem; +import com.azure.storage.blob.models.KeyInfo; import com.azure.storage.blob.models.ListContainersOptions; import com.azure.storage.blob.models.Metadata; import com.azure.storage.blob.models.PublicAccessType; @@ -26,11 +29,12 @@ import java.net.URL; import java.time.OffsetDateTime; +import static com.azure.storage.blob.Utility.postProcessResponse; + /** - * Client to a storage account. It may only be instantiated through a {@link StorageClientBuilder}. - * This class does not hold any state about a particular storage account but is - * instead a convenient way of sending off appropriate requests to the resource on the service. - * It may also be used to construct URLs to blobs and containers. + * Client to a storage account. It may only be instantiated through a {@link StorageClientBuilder}. This class does not + * hold any state about a particular storage account but is instead a convenient way of sending off appropriate requests + * to the resource on the service. It may also be used to construct URLs to blobs and containers. * *

* This client contains operations on a blob. Operations on a container are available on {@link ContainerAsyncClient} @@ -41,36 +45,35 @@ * information on containers. * *

- * Note this client is an async client that returns reactive responses from Spring Reactor Core - * project (https://projectreactor.io/). Calling the methods in this client will NOT - * start the actual network operation, until {@code .subscribe()} is called on the reactive response. - * You can simply convert one of these responses to a {@link java.util.concurrent.CompletableFuture} - * object through {@link Mono#toFuture()}. + * Note this client is an async client that returns reactive responses from Spring Reactor Core project + * (https://projectreactor.io/). Calling the methods in this client will NOT start the actual network + * operation, until {@code .subscribe()} is called on the reactive response. You can simply convert one of these + * responses to a {@link java.util.concurrent.CompletableFuture} object through {@link Mono#toFuture()}. */ public final class StorageAsyncClient { - StorageAsyncRawClient storageAsyncRawClient; + private final AzureBlobStorageImpl azureBlobStorage; /** * Package-private constructor for use by {@link StorageClientBuilder}. + * * @param azureBlobStorageBuilder the API client builder for blob storage API */ StorageAsyncClient(AzureBlobStorageBuilder azureBlobStorageBuilder) { - this.storageAsyncRawClient = new StorageAsyncRawClient(azureBlobStorageBuilder.build()); + this.azureBlobStorage = azureBlobStorageBuilder.build(); } /** - * Initializes a {@link ContainerAsyncClient} object pointing to the specified container. This method does not create a - * container. It simply constructs the URL to the container and offers access to methods relevant to containers. + * Initializes a {@link ContainerAsyncClient} object pointing to the specified container. This method does not + * create a container. It simply constructs the URL to the container and offers access to methods relevant to + * containers. * - * @param containerName - * The name of the container to point to. - * @return - * A {@link ContainerAsyncClient} object pointing to the specified container + * @param containerName The name of the container to point to. + * @return A {@link ContainerAsyncClient} object pointing to the specified container */ public ContainerAsyncClient getContainerAsyncClient(String containerName) { return new ContainerAsyncClient(new AzureBlobStorageBuilder() .url(Utility.appendToURLPath(getAccountUrl(), containerName).toString()) - .pipeline(storageAsyncRawClient.azureBlobStorage.httpPipeline())); + .pipeline(azureBlobStorage.httpPipeline())); } /** @@ -91,11 +94,9 @@ public Mono> createContainer(String containerName * Azure Docs. * * @param containerName Name of the container to create - * @param metadata - * {@link Metadata} - * @param accessType - * Specifies how the data in this container is available to the public. See the x-ms-blob-public-access header - * in the Azure Docs for more information. Pass null for no public access. + * @param metadata {@link Metadata} + * @param accessType Specifies how the data in this container is available to the public. See the + * x-ms-blob-public-access header in the Azure Docs for more information. Pass null for no public access. * @return A response containing a {@link ContainerAsyncClient} used to interact with the container created. */ public Mono> createContainer(String containerName, Metadata metadata, PublicAccessType accessType) { @@ -107,50 +108,76 @@ public Mono> createContainer(String containerName /** * Gets the URL of the storage account represented by this client. + * * @return the URL. * @throws RuntimeException If the account URL is malformed. */ public URL getAccountUrl() { try { - return new URL(storageAsyncRawClient.azureBlobStorage.url()); + return new URL(azureBlobStorage.url()); } catch (MalformedURLException e) { - throw new RuntimeException(String.format("Invalid URL on %s: %s" + getClass().getSimpleName(), storageAsyncRawClient.azureBlobStorage.url()), e); + throw new RuntimeException(String.format("Invalid URL on %s: %s" + getClass().getSimpleName(), azureBlobStorage.url()), e); } } /** - * Returns a reactive Publisher emitting all the containers in this account lazily as needed. For more information, see - * the Azure Docs. + * Returns a reactive Publisher emitting all the containers in this account lazily as needed. For more information, + * see the Azure Docs. * - * @return - * A reactive response emitting the list of containers. + * @return A reactive response emitting the list of containers. */ public Flux listContainers() { return this.listContainers(new ListContainersOptions()); } /** - * Returns a reactive Publisher emitting all the containers in this account lazily as needed. For more information, see + * Returns a reactive Publisher emitting all the containers in this account lazily as needed. For more information, + * see the Azure Docs. + * + * @param options A {@link ListContainersOptions} which specifies what data should be returned by the service. + * @return A reactive response emitting the list of containers. + */ + public Flux listContainers(ListContainersOptions options) { + return listContainersSegment(null, options) + .flatMapMany(response -> listContainersHelper(response.value().marker(), options, response)); + } + + /* + * Returns a Mono segment of containers starting from the specified Marker. + * Use an empty marker to start enumeration from the beginning. Container names are returned in lexicographic order. + * After getting a segment, process it, and then call ListContainers again (passing the the previously-returned + * Marker) to get the next segment. For more information, see * the Azure Docs. * + * @param marker + * Identifies the portion of the list to be returned with the next list operation. + * This value is returned in the response of a previous list operation as the + * ListContainersSegmentResponse.body().nextMarker(). Set to null to list the first segment. * @param options * A {@link ListContainersOptions} which specifies what data should be returned by the service. * - * @return - * A reactive response emitting the list of containers. + * @return Emits the successful response. + * + * @apiNote ## Sample Code \n + * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=service_list "Sample code for ServiceURL.listContainersSegment")] \n + * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=service_list_helper "Helper code for ServiceURL.listContainersSegment")] \n + * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) */ - public Flux listContainers(ListContainersOptions options) { - return storageAsyncRawClient - .listContainersSegment(null, options) - .flatMapMany(response -> listContainersHelper(response.value().marker(), options, response)); + private Mono listContainersSegment(String marker, ListContainersOptions options) { + options = options == null ? new ListContainersOptions() : options; + + return postProcessResponse( + this.azureBlobStorage.services().listContainersSegmentWithRestResponseAsync( + options.prefix(), marker, options.maxResults(), options.details().toIncludeType(), null, + null, Context.NONE)); } private Flux listContainersHelper(String marker, ListContainersOptions options, - ServicesListContainersSegmentResponse response) { + ServicesListContainersSegmentResponse response) { Flux result = Flux.fromIterable(response.value().containerItems()); if (response.value().nextMarker() != null) { // Recursively add the continuation items to the observable. - result = result.concatWith(storageAsyncRawClient.listContainersSegment(marker, options) + result = result.concatWith(listContainersSegment(marker, options) .flatMapMany((r) -> listContainersHelper(response.value().nextMarker(), options, r))); } @@ -162,12 +189,11 @@ private Flux listContainersHelper(String marker, ListContainersOp * Gets the properties of a storage account’s Blob service. For more information, see the * Azure Docs. * - * @return - * A reactive response containing the storage account properties. + * @return A reactive response containing the storage account properties. */ public Mono> getProperties() { - return storageAsyncRawClient - .getProperties() + return postProcessResponse( + this.azureBlobStorage.services().getPropertiesWithRestResponseAsync(null, null, Context.NONE)) .map(rb -> new SimpleResponse<>(rb, rb.value())); } @@ -177,48 +203,50 @@ public Mono> getProperties() { * Note that setting the default service version has no effect when using this client because this client explicitly * sets the version header on each request, overriding the default. * - * @param properties - * Configures the service. - * - * @return - * A reactive response containing the storage account properties. + * @param properties Configures the service. + * @return A reactive response containing the storage account properties. */ public Mono setProperties(StorageServiceProperties properties) { - return storageAsyncRawClient - .setProperties(properties) + return postProcessResponse( + this.azureBlobStorage.services().setPropertiesWithRestResponseAsync(properties, null, null, Context.NONE)) .map(VoidResponse::new); } /** - * Gets a user delegation key for use with this account's blob storage. - * Note: This method call is only valid when using {@link TokenCredential} in this object's {@link HttpPipeline}. - * - * @param start - * Start time for the key's validity. Null indicates immediate start. - * @param expiry - * Expiration of the key's validity. + * Gets a user delegation key for use with this account's blob storage. Note: This method call is only valid when + * using {@link TokenCredential} in this object's {@link HttpPipeline}. * - * @return - * A reactive response containing the user delegation key. + * @param start Start time for the key's validity. Null indicates immediate start. + * @param expiry Expiration of the key's validity. + * @return A reactive response containing the user delegation key. + * @throws IllegalArgumentException If {@code start} isn't null and is after {@code expiry}. */ public Mono> getUserDelegationKey(OffsetDateTime start, OffsetDateTime expiry) { - return storageAsyncRawClient - .getUserDelegationKey(start, expiry) - .map(rb -> new SimpleResponse<>(rb, rb.value())); + Utility.assertNotNull("expiry", expiry); + if (start != null && !start.isBefore(expiry)) { + throw new IllegalArgumentException("`start` must be null or a datetime before `expiry`."); + } + + return postProcessResponse( + this.azureBlobStorage.services().getUserDelegationKeyWithRestResponseAsync( + new KeyInfo() + .start(start == null ? "" : Utility.ISO_8601_UTC_DATE_FORMATTER.format(start)) + .expiry(Utility.ISO_8601_UTC_DATE_FORMATTER.format(expiry)), + null, null, Context.NONE) + ).map(rb -> new SimpleResponse<>(rb, rb.value())); } /** - * Retrieves statistics related to replication for the Blob service. It is only available on the secondary - * location endpoint when read-access geo-redundant replication is enabled for the storage account. For more - * information, see the + * Retrieves statistics related to replication for the Blob service. It is only available on the secondary location + * endpoint when read-access geo-redundant replication is enabled for the storage account. For more information, see + * the * Azure Docs. * - * @return - * A reactive response containing the storage account statistics. + * @return A reactive response containing the storage account statistics. */ public Mono> getStatistics() { - return storageAsyncRawClient - .getStatistics() + return postProcessResponse( + this.azureBlobStorage.services().getStatisticsWithRestResponseAsync(null, null, Context.NONE)) .map(rb -> new SimpleResponse<>(rb, rb.value())); } @@ -226,32 +254,24 @@ public Mono> getStatistics() { * Returns the sku name and account kind for the account. For more information, please see the * Azure Docs. * - * @return - * A reactive response containing the storage account info. + * @return A reactive response containing the storage account info. */ public Mono> getAccountInfo() { - return storageAsyncRawClient - .getAccountInfo() + return postProcessResponse(this.azureBlobStorage.services().getAccountInfoWithRestResponseAsync(Context.NONE)) .map(rb -> new SimpleResponse<>(rb, new StorageAccountInfo(rb.deserializedHeaders()))); } /** * Generates an account SAS token with the specified parameters * - * @param accountSASService - * The {@code AccountSASService} services for the account SAS - * @param accountSASResourceType - * An optional {@code AccountSASResourceType} resources for the account SAS - * @param accountSASPermission - * The {@code AccountSASPermission} permission for the account SAS - * @param expiryTime - * The {@code OffsetDateTime} expiry time for the account SAS - * - * @return - * A string that represents the SAS token + * @param accountSASService The {@code AccountSASService} services for the account SAS + * @param accountSASResourceType An optional {@code AccountSASResourceType} resources for the account SAS + * @param accountSASPermission The {@code AccountSASPermission} permission for the account SAS + * @param expiryTime The {@code OffsetDateTime} expiry time for the account SAS + * @return A string that represents the SAS token */ public String generateAccountSAS(AccountSASService accountSASService, AccountSASResourceType accountSASResourceType, - AccountSASPermission accountSASPermission, OffsetDateTime expiryTime) { + AccountSASPermission accountSASPermission, OffsetDateTime expiryTime) { return this.generateAccountSAS(accountSASService, accountSASResourceType, accountSASPermission, expiryTime, null /* startTime */, null /* version */, null /* ipRange */, null /* sasProtocol */); } @@ -259,29 +279,19 @@ public String generateAccountSAS(AccountSASService accountSASService, AccountSAS /** * Generates an account SAS token with the specified parameters * - * @param accountSASService - * The {@code AccountSASService} services for the account SAS - * @param accountSASResourceType - * An optional {@code AccountSASResourceType} resources for the account SAS - * @param accountSASPermission - * The {@code AccountSASPermission} permission for the account SAS - * @param expiryTime - * The {@code OffsetDateTime} expiry time for the account SAS - * @param startTime - * The {@code OffsetDateTime} start time for the account SAS - * @param version - * The {@code String} version for the account SAS - * @param ipRange - * An optional {@code IPRange} ip address range for the SAS - * @param sasProtocol - * An optional {@code SASProtocol} protocol for the SAS - * - * @return - * A string that represents the SAS token + * @param accountSASService The {@code AccountSASService} services for the account SAS + * @param accountSASResourceType An optional {@code AccountSASResourceType} resources for the account SAS + * @param accountSASPermission The {@code AccountSASPermission} permission for the account SAS + * @param expiryTime The {@code OffsetDateTime} expiry time for the account SAS + * @param startTime The {@code OffsetDateTime} start time for the account SAS + * @param version The {@code String} version for the account SAS + * @param ipRange An optional {@code IPRange} ip address range for the SAS + * @param sasProtocol An optional {@code SASProtocol} protocol for the SAS + * @return A string that represents the SAS token */ public String generateAccountSAS(AccountSASService accountSASService, AccountSASResourceType accountSASResourceType, - AccountSASPermission accountSASPermission, OffsetDateTime expiryTime, OffsetDateTime startTime, String version, IPRange ipRange, - SASProtocol sasProtocol) { + AccountSASPermission accountSASPermission, OffsetDateTime expiryTime, OffsetDateTime startTime, String version, IPRange ipRange, + SASProtocol sasProtocol) { AccountSASSignatureValues accountSASSignatureValues = new AccountSASSignatureValues(); accountSASSignatureValues.services(accountSASService == null ? null : accountSASService.toString()); @@ -297,7 +307,7 @@ public String generateAccountSAS(AccountSASService accountSASService, AccountSAS accountSASSignatureValues.ipRange(ipRange); accountSASSignatureValues.protocol(sasProtocol); - SharedKeyCredential sharedKeyCredential = Utility.getSharedKeyCredential(this.storageAsyncRawClient.azureBlobStorage.httpPipeline()); + SharedKeyCredential sharedKeyCredential = Utility.getSharedKeyCredential(this.azureBlobStorage.httpPipeline()); SASQueryParameters sasQueryParameters = accountSASSignatureValues.generateSASQueryParameters(sharedKeyCredential); diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/StorageAsyncRawClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/StorageAsyncRawClient.java deleted file mode 100644 index a2b6be965ed30..0000000000000 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/StorageAsyncRawClient.java +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.azure.storage.blob; - -import com.azure.core.credentials.TokenCredential; -import com.azure.core.http.HttpPipeline; -import com.azure.core.util.Context; -import com.azure.storage.blob.implementation.AzureBlobStorageImpl; -import com.azure.storage.blob.models.KeyInfo; -import com.azure.storage.blob.models.ListContainersOptions; -import com.azure.storage.blob.models.ServicesGetAccountInfoResponse; -import com.azure.storage.blob.models.ServicesGetPropertiesResponse; -import com.azure.storage.blob.models.ServicesGetStatisticsResponse; -import com.azure.storage.blob.models.ServicesGetUserDelegationKeyResponse; -import com.azure.storage.blob.models.ServicesListContainersSegmentResponse; -import com.azure.storage.blob.models.ServicesSetPropertiesResponse; -import com.azure.storage.blob.models.StorageServiceProperties; -import reactor.core.publisher.Mono; - -import java.time.OffsetDateTime; - -import static com.azure.storage.blob.Utility.postProcessResponse; - -/** - * Represents a URL to a storage service. This class does not hold any state about a particular storage account but is - * instead a convenient way of sending off appropriate requests to the resource on the service. - * It may also be used to construct URLs to blobs and containers. - * Please see here for more - * information on containers. - */ -final class StorageAsyncRawClient { - - final AzureBlobStorageImpl azureBlobStorage; - - /** - * Creates a {@code ServiceURL} object pointing to the account specified by the URL and using the provided pipeline - * to make HTTP requests. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=service_url "Sample code for ServiceURL constructor")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - StorageAsyncRawClient(AzureBlobStorageImpl azureBlobStorage) { - this.azureBlobStorage = azureBlobStorage; - } - - /** - * Returns a Mono segment of containers starting from the specified Marker. - * Use an empty marker to start enumeration from the beginning. Container names are returned in lexicographic order. - * After getting a segment, process it, and then call ListContainers again (passing the the previously-returned - * Marker) to get the next segment. For more information, see - * the Azure Docs. - * - * @param marker - * Identifies the portion of the list to be returned with the next list operation. - * This value is returned in the response of a previous list operation as the - * ListContainersSegmentResponse.body().nextMarker(). Set to null to list the first segment. - * @param options - * A {@link ListContainersOptions} which specifies what data should be returned by the service. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=service_list "Sample code for ServiceURL.listContainersSegment")] \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=service_list_helper "Helper code for ServiceURL.listContainersSegment")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono listContainersSegment(String marker, - ListContainersOptions options) { - options = options == null ? new ListContainersOptions() : options; - - return postProcessResponse( - this.azureBlobStorage.services().listContainersSegmentWithRestResponseAsync( - options.prefix(), marker, options.maxResults(), options.details().toIncludeType(), null, - null, Context.NONE)); - } - - /** - * Gets the properties of a storage account’s Blob service. For more information, see the - * Azure Docs. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=service_getsetprops "Sample code for ServiceURL.getProperties")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono getProperties() { - return postProcessResponse( - this.azureBlobStorage.services().getPropertiesWithRestResponseAsync(null, null, Context.NONE)); - } - - /** - * Sets properties for a storage account's Blob service endpoint. For more information, see the - * Azure Docs. - * Note that setting the default service version has no effect when using this client because this client explicitly - * sets the version header on each request, overriding the default. - * - * @param properties - * Configures the service. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=service_getsetprops "Sample code for ServiceURL.setProperties")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono setProperties(StorageServiceProperties properties) { - return postProcessResponse( - this.azureBlobStorage.services().setPropertiesWithRestResponseAsync(properties, null, null, Context.NONE)); - } - - /** - * Gets a user delegation key for use with this account's blob storage. - * Note: This method call is only valid when using {@link TokenCredential} in this object's {@link HttpPipeline}. - * - * @param start - * Start time for the key's validity. Null indicates immediate start. - * @param expiry - * Expiration of the key's validity. - * - * @return Emits the successful response. - * @throws IllegalArgumentException If {@code start} isn't null and is after {@code expiry}. - */ - public Mono getUserDelegationKey(OffsetDateTime start, OffsetDateTime expiry) { - Utility.assertNotNull("expiry", expiry); - if (start != null && !start.isBefore(expiry)) { - throw new IllegalArgumentException("`start` must be null or a datetime before `expiry`."); - } - - return postProcessResponse( - this.azureBlobStorage.services().getUserDelegationKeyWithRestResponseAsync( - new KeyInfo() - .start(start == null ? "" : Utility.ISO_8601_UTC_DATE_FORMATTER.format(start)) - .expiry(Utility.ISO_8601_UTC_DATE_FORMATTER.format(expiry)), - null, null, Context.NONE) - ); - } - - /** - * Retrieves statistics related to replication for the Blob service. It is only available on the secondary - * location endpoint when read-access geo-redundant replication is enabled for the storage account. For more - * information, see the - * Azure Docs. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=service_stats "Sample code for ServiceURL.getStats")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono getStatistics() { - return postProcessResponse( - this.azureBlobStorage.services().getStatisticsWithRestResponseAsync(null, null, Context.NONE)); - } - - /** - * Returns the sku name and account kind for the account. For more information, please see the - * Azure Docs. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=account_info "Sample code for ServiceURL.getAccountInfo")] \n - * For more samples, please see the [Samples file] (https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public Mono getAccountInfo() { - return postProcessResponse( - this.azureBlobStorage.services().getAccountInfoWithRestResponseAsync(Context.NONE)); - } -} diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/StorageClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/StorageClient.java index c895cdda58bbc..1511726d653bb 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/StorageClient.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/StorageClient.java @@ -24,25 +24,24 @@ import java.time.OffsetDateTime; /** - * Client to a storage account. It may only be instantiated through a {@link StorageClientBuilder}. - * This class does not hold any state about a particular storage account but is - * instead a convenient way of sending off appropriate requests to the resource on the service. - * It may also be used to construct URLs to blobs and containers. + * Client to a storage account. It may only be instantiated through a {@link StorageClientBuilder}. This class does not + * hold any state about a particular storage account but is instead a convenient way of sending off appropriate requests + * to the resource on the service. It may also be used to construct URLs to blobs and containers. * *

- * This client contains operations on a blob. Operations on a container are available on {@link ContainerClient} - * through {@link #getContainerClient(String)}, and operations on a blob are available on {@link BlobClient}. + * This client contains operations on a blob. Operations on a container are available on {@link ContainerClient} through + * {@link #getContainerClient(String)}, and operations on a blob are available on {@link BlobClient}. * *

* Please see here for more * information on containers. */ public final class StorageClient { - - private StorageAsyncClient storageAsyncClient; + private final StorageAsyncClient storageAsyncClient; /** * Package-private constructor for use by {@link StorageClientBuilder}. + * * @param storageAsyncClient the async storage account client */ StorageClient(StorageAsyncClient storageAsyncClient) { @@ -53,10 +52,8 @@ public final class StorageClient { * Initializes a {@link ContainerClient} object pointing to the specified container. This method does not create a * container. It simply constructs the URL to the container and offers access to methods relevant to containers. * - * @param containerName - * The name of the container to point to. - * @return - * A {@link ContainerClient} object pointing to the specified container + * @param containerName The name of the container to point to. + * @return A {@link ContainerClient} object pointing to the specified container */ public ContainerClient getContainerClient(String containerName) { return new ContainerClient(storageAsyncClient.getContainerAsyncClient(containerName)); @@ -80,11 +77,9 @@ public Response createContainer(String containerName) { * Azure Docs. * * @param containerName Name of the container to create - * @param metadata - * {@link Metadata} - * @param accessType - * Specifies how the data in this container is available to the public. See the x-ms-blob-public-access header - * in the Azure Docs for more information. Pass null for no public access. + * @param metadata {@link Metadata} + * @param accessType Specifies how the data in this container is available to the public. See the + * x-ms-blob-public-access header in the Azure Docs for more information. Pass null for no public access. * @return A response containing a {@link ContainerClient} used to interact with the container created. */ public Response createContainer(String containerName, Metadata metadata, PublicAccessType accessType) { @@ -95,6 +90,7 @@ public Response createContainer(String containerName, Metadata /** * Gets the URL of the storage account represented by this client. + * * @return the URL. */ public URL getAccountUrl() { @@ -102,29 +98,24 @@ public URL getAccountUrl() { } /** - * Returns a lazy loaded list of containers in this account. The returned {@link Iterable} can be iterated - * through while new items are automatically retrieved as needed. For more information, see - * the Azure Docs. + * Returns a lazy loaded list of containers in this account. The returned {@link Iterable} can be iterated through + * while new items are automatically retrieved as needed. For more information, see the Azure Docs. * - * @return - * The list of containers. + * @return The list of containers. */ public Iterable listContainers() { return this.listContainers(new ListContainersOptions(), null); } /** - * Returns a lazy loaded list of containers in this account. The returned {@link Iterable} can be iterated - * through while new items are automatically retrieved as needed. For more information, see - * the Azure Docs. - * - * @param options - * A {@link ListContainersOptions} which specifies what data should be returned by the service. - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. + * Returns a lazy loaded list of containers in this account. The returned {@link Iterable} can be iterated through + * while new items are automatically retrieved as needed. For more information, see the Azure Docs. * - * @return - * The list of containers. + * @param options A {@link ListContainersOptions} which specifies what data should be returned by the service. + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @return The list of containers. */ public Iterable listContainers(ListContainersOptions options, Duration timeout) { Flux response = storageAsyncClient.listContainers(options); @@ -136,8 +127,7 @@ public Iterable listContainers(ListContainersOptions options, Dur * Gets the properties of a storage account’s Blob service. For more information, see the * Azure Docs. * - * @return - * The storage account properties. + * @return The storage account properties. */ public Response getProperties() { return this.getProperties(null); @@ -147,11 +137,8 @@ public Response getProperties() { * Gets the properties of a storage account’s Blob service. For more information, see the * Azure Docs. * - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. - * - * @return - * The storage account properties. + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @return The storage account properties. */ public Response getProperties(Duration timeout) { @@ -166,11 +153,8 @@ public Response getProperties(Duration timeout) { * Note that setting the default service version has no effect when using this client because this client explicitly * sets the version header on each request, overriding the default. * - * @param properties - * Configures the service. - * - * @return - * The storage account properties. + * @param properties Configures the service. + * @return The storage account properties. */ public VoidResponse setProperties(StorageServiceProperties properties) { return this.setProperties(properties, null); @@ -182,13 +166,9 @@ public VoidResponse setProperties(StorageServiceProperties properties) { * Note that setting the default service version has no effect when using this client because this client explicitly * sets the version header on each request, overriding the default. * - * @param properties - * Configures the service. - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. - * - * @return - * The storage account properties. + * @param properties Configures the service. + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @return The storage account properties. */ public VoidResponse setProperties(StorageServiceProperties properties, Duration timeout) { Mono response = storageAsyncClient.setProperties(properties); @@ -197,66 +177,53 @@ public VoidResponse setProperties(StorageServiceProperties properties, Duration } /** - * Gets a user delegation key for use with this account's blob storage. - * Note: This method call is only valid when using {@link TokenCredential} in this object's {@link HttpPipeline}. + * Gets a user delegation key for use with this account's blob storage. Note: This method call is only valid when + * using {@link TokenCredential} in this object's {@link HttpPipeline}. * - * @param start - * Start time for the key's validity. Null indicates immediate start. - * @param expiry - * Expiration of the key's validity. - * - * @return - * The user delegation key. + * @param start Start time for the key's validity. Null indicates immediate start. + * @param expiry Expiration of the key's validity. + * @return The user delegation key. */ public Response getUserDelegationKey(OffsetDateTime start, OffsetDateTime expiry) { return this.getUserDelegationKey(start, expiry, null); } /** - * Gets a user delegation key for use with this account's blob storage. - * Note: This method call is only valid when using {@link TokenCredential} in this object's {@link HttpPipeline}. - * - * @param start - * Start time for the key's validity. Null indicates immediate start. - * @param expiry - * Expiration of the key's validity. - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. + * Gets a user delegation key for use with this account's blob storage. Note: This method call is only valid when + * using {@link TokenCredential} in this object's {@link HttpPipeline}. * - * @return - * The user delegation key. + * @param start Start time for the key's validity. Null indicates immediate start. + * @param expiry Expiration of the key's validity. + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @return The user delegation key. */ public Response getUserDelegationKey(OffsetDateTime start, OffsetDateTime expiry, - Duration timeout) { + Duration timeout) { Mono> response = storageAsyncClient.getUserDelegationKey(start, expiry); return Utility.blockWithOptionalTimeout(response, timeout); } /** - * Retrieves statistics related to replication for the Blob service. It is only available on the secondary - * location endpoint when read-access geo-redundant replication is enabled for the storage account. For more - * information, see the + * Retrieves statistics related to replication for the Blob service. It is only available on the secondary location + * endpoint when read-access geo-redundant replication is enabled for the storage account. For more information, see + * the * Azure Docs. * - * @return - * The storage account statistics. + * @return The storage account statistics. */ public Response getStatistics() { return this.getStatistics(null); } /** - * Retrieves statistics related to replication for the Blob service. It is only available on the secondary - * location endpoint when read-access geo-redundant replication is enabled for the storage account. For more - * information, see the + * Retrieves statistics related to replication for the Blob service. It is only available on the secondary location + * endpoint when read-access geo-redundant replication is enabled for the storage account. For more information, see + * the * Azure Docs. * - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. - * - * @return - * The storage account statistics. + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @return The storage account statistics. */ public Response getStatistics(Duration timeout) { Mono> response = storageAsyncClient.getStatistics(); @@ -268,8 +235,7 @@ public Response getStatistics(Duration timeout) { * Returns the sku name and account kind for the account. For more information, please see the * Azure Docs. * - * @return - * The storage account info. + * @return The storage account info. */ public Response getAccountInfo() { return this.getAccountInfo(null); @@ -279,11 +245,8 @@ public Response getAccountInfo() { * Returns the sku name and account kind for the account. For more information, please see the * Azure Docs. * - * @param timeout - * An optional timeout value beyond which a {@link RuntimeException} will be raised. - * - * @return - * The storage account info. + * @param timeout An optional timeout value beyond which a {@link RuntimeException} will be raised. + * @return The storage account info. */ public Response getAccountInfo(Duration timeout) { Mono> response = storageAsyncClient.getAccountInfo(); @@ -294,49 +257,33 @@ public Response getAccountInfo(Duration timeout) { /** * Generates an account SAS token with the specified parameters * - * @param accountSASService - * The {@code AccountSASService} services for the account SAS - * @param accountSASResourceType - * An optional {@code AccountSASResourceType} resources for the account SAS - * @param accountSASPermission - * The {@code AccountSASPermission} permission for the account SAS - * @param expiryTime - * The {@code OffsetDateTime} expiry time for the account SAS - * - * @return - * A string that represents the SAS token + * @param accountSASService The {@code AccountSASService} services for the account SAS + * @param accountSASResourceType An optional {@code AccountSASResourceType} resources for the account SAS + * @param accountSASPermission The {@code AccountSASPermission} permission for the account SAS + * @param expiryTime The {@code OffsetDateTime} expiry time for the account SAS + * @return A string that represents the SAS token */ public String generateAccountSAS(AccountSASService accountSASService, AccountSASResourceType accountSASResourceType, - AccountSASPermission accountSASPermission, OffsetDateTime expiryTime) { + AccountSASPermission accountSASPermission, OffsetDateTime expiryTime) { return this.storageAsyncClient.generateAccountSAS(accountSASService, accountSASResourceType, accountSASPermission, expiryTime); } /** * Generates an account SAS token with the specified parameters * - * @param accountSASService - * The {@code AccountSASService} services for the account SAS - * @param accountSASResourceType - * An optional {@code AccountSASResourceType} resources for the account SAS - * @param accountSASPermission - * The {@code AccountSASPermission} permission for the account SAS - * @param expiryTime - * The {@code OffsetDateTime} expiry time for the account SAS - * @param startTime - * The {@code OffsetDateTime} start time for the account SAS - * @param version - * The {@code String} version for the account SAS - * @param ipRange - * An optional {@code IPRange} ip address range for the SAS - * @param sasProtocol - * An optional {@code SASProtocol} protocol for the SAS - * - * @return - * A string that represents the SAS token + * @param accountSASService The {@code AccountSASService} services for the account SAS + * @param accountSASResourceType An optional {@code AccountSASResourceType} resources for the account SAS + * @param accountSASPermission The {@code AccountSASPermission} permission for the account SAS + * @param expiryTime The {@code OffsetDateTime} expiry time for the account SAS + * @param startTime The {@code OffsetDateTime} start time for the account SAS + * @param version The {@code String} version for the account SAS + * @param ipRange An optional {@code IPRange} ip address range for the SAS + * @param sasProtocol An optional {@code SASProtocol} protocol for the SAS + * @return A string that represents the SAS token */ public String generateAccountSAS(AccountSASService accountSASService, AccountSASResourceType accountSASResourceType, - AccountSASPermission accountSASPermission, OffsetDateTime expiryTime, OffsetDateTime startTime, String version, IPRange ipRange, - SASProtocol sasProtocol) { + AccountSASPermission accountSASPermission, OffsetDateTime expiryTime, OffsetDateTime startTime, String version, IPRange ipRange, + SASProtocol sasProtocol) { return this.storageAsyncClient.generateAccountSAS(accountSASService, accountSASResourceType, accountSASPermission, expiryTime, startTime, version, ipRange, sasProtocol); } } diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/StorageRawClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/StorageRawClient.java deleted file mode 100644 index cebfdc451ae67..0000000000000 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/StorageRawClient.java +++ /dev/null @@ -1,259 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.azure.storage.blob; - -import com.azure.core.http.HttpPipeline; -import com.azure.storage.blob.implementation.AzureBlobStorageImpl; -import com.azure.storage.blob.models.ListContainersOptions; -import com.azure.storage.blob.models.ServicesGetAccountInfoResponse; -import com.azure.storage.blob.models.ServicesGetPropertiesResponse; -import com.azure.storage.blob.models.ServicesGetStatisticsResponse; -import com.azure.storage.blob.models.ServicesGetUserDelegationKeyResponse; -import com.azure.storage.blob.models.ServicesListContainersSegmentResponse; -import com.azure.storage.blob.models.ServicesSetPropertiesResponse; -import com.azure.storage.blob.models.StorageServiceProperties; -import com.azure.storage.common.credentials.SASTokenCredential; -import reactor.core.publisher.Mono; - -import java.time.Duration; -import java.time.OffsetDateTime; - -/** - * Represents a URL to a storage service. This class does not hold any state about a particular storage account but is - * instead a convenient way of sending off appropriate requests to the resource on the service. - * It may also be used to construct URLs to blobs and containers. - * Please see here for more - * information on containers. - */ -final class StorageRawClient { - - StorageAsyncRawClient storageAsyncRawClient; - - /** - * Creates a {@code ServiceURL} object pointing to the account specified by the URL and using the provided pipeline - * to make HTTP requests. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=service_url "Sample code for ServiceURL constructor")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - StorageRawClient(AzureBlobStorageImpl azureBlobStorage) { - this.storageAsyncRawClient = new StorageAsyncRawClient(azureBlobStorage); - } - - /** - * Returns a Mono segment of containers starting from the specified Marker. - * Use an empty marker to start enumeration from the beginning. Container names are returned in lexicographic order. - * After getting a segment, process it, and then call ListContainers again (passing the the previously-returned - * Marker) to get the next segment. For more information, see - * the Azure Docs. - * - * @param marker - * Identifies the portion of the list to be returned with the next list operation. - * This value is returned in the response of a previous list operation as the - * ListContainersSegmentResponse.body().nextMarker(). Set to null to list the first segment. - * @param options - * A {@link ListContainersOptions} which specifies what data should be returned by the service. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=service_list "Sample code for ServiceURL.listContainersSegment")] \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=service_list_helper "Helper code for ServiceURL.listContainersSegment")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ServicesListContainersSegmentResponse listContainersSegment(String marker, - ListContainersOptions options) { - return this.listContainersSegment(marker, options, null); - } - - /** - * Returns a Mono segment of containers starting from the specified Marker. - * Use an empty marker to start enumeration from the beginning. Container names are returned in lexicographic order. - * After getting a segment, process it, and then call ListContainers again (passing the the previously-returned - * Marker) to get the next segment. For more information, see - * the Azure Docs. - * - * @param marker - * Identifies the portion of the list to be returned with the next list operation. - * This value is returned in the response of a previous list operation as the - * ListContainersSegmentResponse.body().nextMarker(). Set to null to list the first segment. - * @param options - * A {@link ListContainersOptions} which specifies what data should be returned by the service. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=service_list "Sample code for ServiceURL.listContainersSegment")] \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=service_list_helper "Helper code for ServiceURL.listContainersSegment")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ServicesListContainersSegmentResponse listContainersSegment(String marker, - ListContainersOptions options, Duration timeout) { - Mono response = storageAsyncRawClient.listContainersSegment(marker, options); - return Utility.blockWithOptionalTimeout(response, timeout); - } - - /** - * Gets the properties of a storage account’s Blob service. For more information, see the - * Azure Docs. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=service_getsetprops "Sample code for ServiceURL.getProperties")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ServicesGetPropertiesResponse getProperties() { - return this.getProperties(null); - } - - /** - * Gets the properties of a storage account’s Blob service. For more information, see the - * Azure Docs. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=service_getsetprops "Sample code for ServiceURL.getProperties")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ServicesGetPropertiesResponse getProperties(Duration timeout) { - Mono response = storageAsyncRawClient.getProperties(); - return Utility.blockWithOptionalTimeout(response, timeout); - } - - /** - * Sets properties for a storage account's Blob service endpoint. For more information, see the - * Azure Docs. - * Note that setting the default service version has no effect when using this client because this client explicitly - * sets the version header on each request, overriding the default. - * - * @param properties - * Configures the service. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=service_getsetprops "Sample code for ServiceURL.setProperties")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ServicesSetPropertiesResponse setProperties(StorageServiceProperties properties) { - return this.setProperties(properties, null); - } - - /** - * Sets properties for a storage account's Blob service endpoint. For more information, see the - * Azure Docs. - * Note that setting the default service version has no effect when using this client because this client explicitly - * sets the version header on each request, overriding the default. - * - * @param properties - * Configures the service. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=service_getsetprops "Sample code for ServiceURL.setProperties")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ServicesSetPropertiesResponse setProperties(StorageServiceProperties properties, Duration timeout) { - Mono response = storageAsyncRawClient.setProperties(properties); - return Utility.blockWithOptionalTimeout(response, timeout); - } - - /** - * Gets a user delegation key for use with this account's blob storage. - * Note: This method call is only valid when using {@link SASTokenCredential} in this object's {@link HttpPipeline}. - * - * @param start - * Start time for the key's validity. Null indicates immediate start. - * @param expiry - * Expiration of the key's validity. - * - * @return Emits the successful response. - */ - public ServicesGetUserDelegationKeyResponse getUserDelegationKey(OffsetDateTime start, OffsetDateTime expiry) { - return this.getUserDelegationKey(start, expiry, null); - } - - /** - * Gets a user delegation key for use with this account's blob storage. - * Note: This method call is only valid when using {@link SASTokenCredential} in this object's {@link HttpPipeline}. - * - * @param start - * Start time for the key's validity. Null indicates immediate start. - * @param expiry - * Expiration of the key's validity. - * - * @return Emits the successful response. - */ - public ServicesGetUserDelegationKeyResponse getUserDelegationKey(OffsetDateTime start, OffsetDateTime expiry, - Duration timeout) { - Mono response = storageAsyncRawClient.getUserDelegationKey(start, expiry); - return Utility.blockWithOptionalTimeout(response, timeout); - } - - /** - * Retrieves statistics related to replication for the Blob service. It is only available on the secondary - * location endpoint when read-access geo-redundant replication is enabled for the storage account. For more - * information, see the - * Azure Docs. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=service_stats "Sample code for ServiceURL.getStats")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ServicesGetStatisticsResponse getStatistics() { - return this.getStatistics(null); - } - - /** - * Retrieves statistics related to replication for the Blob service. It is only available on the secondary - * location endpoint when read-access geo-redundant replication is enabled for the storage account. For more - * information, see the - * Azure Docs. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=service_stats "Sample code for ServiceURL.getStats")] \n - * For more samples, please see the [Samples file](%https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ServicesGetStatisticsResponse getStatistics(Duration timeout) { - Mono response = storageAsyncRawClient.getStatistics(); - return Utility.blockWithOptionalTimeout(response, timeout); - } - - /** - * Returns the sku name and account kind for the account. For more information, please see the - * Azure Docs. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=account_info "Sample code for ServiceURL.getAccountInfo")] \n - * For more samples, please see the [Samples file] (https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ServicesGetAccountInfoResponse getAccountInfo() { - return this.getAccountInfo(null); - } - - /** - * Returns the sku name and account kind for the account. For more information, please see the - * Azure Docs. - * - * @return Emits the successful response. - * - * @apiNote ## Sample Code \n - * [!code-java[Sample_Code](../azure-storage-java/src/test/java/com/microsoft/azure/storage/Samples.java?name=account_info "Sample code for ServiceURL.getAccountInfo")] \n - * For more samples, please see the [Samples file] (https://github.com/Azure/azure-storage-java/blob/master/src/test/java/com/microsoft/azure/storage/Samples.java) - */ - public ServicesGetAccountInfoResponse getAccountInfo(Duration timeout) { - Mono response = storageAsyncRawClient.getAccountInfo(); - return Utility.blockWithOptionalTimeout(response, timeout); - } -} diff --git a/storage/client/blob/src/main/java/com/azure/storage/common/credentials/SASTokenCredential.java b/storage/client/blob/src/main/java/com/azure/storage/common/credentials/SASTokenCredential.java index 4dce1c831ce21..cff7bc91f7765 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/common/credentials/SASTokenCredential.java +++ b/storage/client/blob/src/main/java/com/azure/storage/common/credentials/SASTokenCredential.java @@ -43,6 +43,7 @@ public final class SASTokenCredential { /** * Creates a SAS token credential from the passed SAS token. + * * @param sasToken SAS token used to authenticate requests with the service. */ public SASTokenCredential(String sasToken) { @@ -58,6 +59,7 @@ public String sasToken() { /** * Creates a SAS token credential from the passed URL query string + * * @param query URL query used to build the SAS token * @return a SAS token credential if the query param contains all the necessary pieces */ diff --git a/storage/client/blob/src/main/java/com/azure/storage/common/policy/SharedKeyCredentialPolicy.java b/storage/client/blob/src/main/java/com/azure/storage/common/policy/SharedKeyCredentialPolicy.java index 743eae8f262e4..e8b54914cb762 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/common/policy/SharedKeyCredentialPolicy.java +++ b/storage/client/blob/src/main/java/com/azure/storage/common/policy/SharedKeyCredentialPolicy.java @@ -18,6 +18,7 @@ public final class SharedKeyCredentialPolicy implements HttpPipelinePolicy { /** * Creates a SharedKey pipeline policy that adds the SharedKey into the request's authorization header. + * * @param credential the SharedKey credential used to create the policy. */ public SharedKeyCredentialPolicy(SharedKeyCredential credential) { @@ -25,9 +26,7 @@ public SharedKeyCredentialPolicy(SharedKeyCredential credential) { } /** - * Gets the shared key credential linked to the policy. - * @return - * The {@link SharedKeyCredential} linked to the policy. + * @return the {@link SharedKeyCredential} linked to the policy. */ public SharedKeyCredential sharedKeyCredential() { return this.credential; diff --git a/storage/client/blob/src/test/java/com/azure/storage/blob/Sample.java b/storage/client/blob/src/test/java/com/azure/storage/blob/Sample.java index 1ac12cbe978da..f6d19d6b84167 100644 --- a/storage/client/blob/src/test/java/com/azure/storage/blob/Sample.java +++ b/storage/client/blob/src/test/java/com/azure/storage/blob/Sample.java @@ -8,6 +8,8 @@ import com.azure.storage.blob.models.BlobItem; import com.azure.storage.blob.models.ContainerItem; import com.azure.storage.common.credentials.SharedKeyCredential; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -16,7 +18,6 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.UUID; @@ -116,8 +117,7 @@ public void asyncSample() throws IOException { for (int i = 0; i < 5; i++) { BlockBlobAsyncClient blobClient = finalContainerClient.getBlockBlobAsyncClient("testblob-" + i); byte[] message = ("test data" + i).getBytes(StandardCharsets.UTF_8); - Flux testdata = Flux.just(ByteBuffer.wrap(message)); - + Flux testdata = Flux.just(ByteBufAllocator.DEFAULT.buffer(message.length).writeBytes(message)); finished = finished.and(blobClient.upload(testdata, message.length) .then(Mono.defer(() -> { From 10a85ad6248cf26c06c045e31a822129ad631b4f Mon Sep 17 00:00:00 2001 From: Jianghao Lu Date: Wed, 17 Jul 2019 14:22:17 -0700 Subject: [PATCH 03/17] Add storage swaggers --- storage/client/blob/swagger/blob.json | 8701 +++++++++++++++++++++++ storage/client/file/swagger/file.json | 3616 ++++++++++ storage/client/queue/swagger/queue.json | 1856 +++++ 3 files changed, 14173 insertions(+) create mode 100644 storage/client/blob/swagger/blob.json create mode 100644 storage/client/file/swagger/file.json create mode 100644 storage/client/queue/swagger/queue.json diff --git a/storage/client/blob/swagger/blob.json b/storage/client/blob/swagger/blob.json new file mode 100644 index 0000000000000..4a89d47458cc3 --- /dev/null +++ b/storage/client/blob/swagger/blob.json @@ -0,0 +1,8701 @@ +{ + "swagger": "2.0", + "info": { + "title": "Azure Blob Storage", + "version": "2018-11-09", + "x-ms-code-generation-settings": { + "header": "MIT", + "strictSpecAdherence": false + } + }, + "x-ms-parameterized-host": { + "hostTemplate": "{url}", + "useSchemePrefix": false, + "positionInOperation": "first", + "parameters": [ + { + "$ref": "#/parameters/Url" + } + ] + }, + "securityDefinitions": { + "blob_shared_key": { + "type": "apiKey", + "name": "Authorization", + "in": "header" + } + }, + "schemes": [ + "https" + ], + "consumes": [ + "application/xml" + ], + "produces": [ + "application/xml" + ], + "paths": {}, + "x-ms-paths": { + "/?restype=service&comp=properties": { + "put": { + "tags": [ + "service" + ], + "operationId": "Service_SetProperties", + "description": "Sets properties for a storage account's Blob service endpoint, including properties for Storage Analytics and CORS (Cross-Origin Resource Sharing) rules", + "parameters": [ + { + "$ref": "#/parameters/StorageServiceProperties" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "202": { + "description": "Success (Accepted)", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "get": { + "tags": [ + "service" + ], + "operationId": "Service_GetProperties", + "description": "gets the properties of a storage account's Blob service, including properties for Storage Analytics and CORS (Cross-Origin Resource Sharing) rules.", + "parameters": [ + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "Success.", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + } + }, + "schema": { + "$ref": "#/definitions/StorageServiceProperties" + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "restype", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "service" + ] + }, + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "properties" + ] + } + ] + }, + "/?restype=service&comp=stats": { + "get": { + "tags": [ + "service" + ], + "operationId": "Service_GetStatistics", + "description": "Retrieves statistics related to replication for the Blob service. It is only available on the secondary location endpoint when read-access geo-redundant replication is enabled for the storage account.", + "parameters": [ + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "Success.", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + }, + "schema": { + "$ref": "#/definitions/StorageServiceStats" + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "restype", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "service" + ] + }, + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "stats" + ] + } + ] + }, + "/?comp=list": { + "get": { + "tags": [ + "service" + ], + "operationId": "Service_ListContainersSegment", + "description": "The List Containers Segment operation returns a list of the containers under the specified account", + "parameters": [ + { + "$ref": "#/parameters/Prefix" + }, + { + "$ref": "#/parameters/Marker" + }, + { + "$ref": "#/parameters/MaxResults" + }, + { + "$ref": "#/parameters/ListContainersInclude" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "Success.", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + } + }, + "schema": { + "$ref": "#/definitions/ListContainersSegmentResponse" + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "NextMarker" + } + }, + "parameters": [ + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "list" + ] + } + ] + }, + "/?restype=service&comp=userdelegationkey": { + "post": { + "tags": [ + "service" + ], + "operationId": "Service_GetUserDelegationKey", + "description": "Retrieves a user delgation key for the Blob service. This is only a valid operation when using bearer token authentication.", + "parameters": [ + { + "$ref": "#/parameters/KeyInfo" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "Success.", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + }, + "schema": { + "$ref": "#/definitions/UserDelegationKey" + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "restype", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "service" + ] + }, + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "userdelegationkey" + ] + } + ] + }, + "/?restype=account&comp=properties": { + "get": { + "tags": [ + "service" + ], + "operationId": "Service_GetAccountInfo", + "description": "Returns the sku name and account kind ", + "parameters": [ + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Success (OK)", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + }, + "x-ms-sku-name": { + "x-ms-client-name": "SkuName", + "type": "string", + "enum": [ + "Standard_LRS", + "Standard_GRS", + "Standard_RAGRS", + "Standard_ZRS", + "Premium_LRS" + ], + "x-ms-enum": { + "name": "SkuName", + "modelAsString": false + }, + "description": "Identifies the sku name of the account" + }, + "x-ms-account-kind": { + "x-ms-client-name": "AccountKind", + "type": "string", + "enum": [ + "Storage", + "BlobStorage", + "StorageV2" + ], + "x-ms-enum": { + "name": "AccountKind", + "modelAsString": false + }, + "description": "Identifies the account kind" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "restype", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "account" + ] + }, + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "properties" + ] + } + ] + }, + "/{containerName}?restype=container": { + "put": { + "tags": [ + "container" + ], + "operationId": "Container_Create", + "description": "creates a new container under the specified account. If the container with the same name already exists, the operation fails", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/Metadata" + }, + { + "$ref": "#/parameters/BlobPublicAccess" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "201": { + "description": "Success, Container created.", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the container was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "get": { + "tags": [ + "container" + ], + "operationId": "Container_GetProperties", + "description": "returns all user-defined metadata and system properties for the specified container. The data returned does not include the container's list of blobs", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/LeaseIdOptional" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "x-ms-meta": { + "type": "string", + "x-ms-client-name": "Metadata", + "x-ms-header-collection-prefix": "x-ms-meta-" + }, + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the container was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "x-ms-lease-duration": { + "x-ms-client-name": "LeaseDuration", + "description": "When a blob is leased, specifies whether the lease is of infinite or fixed duration.", + "type": "string", + "enum": [ + "infinite", + "fixed" + ], + "x-ms-enum": { + "name": "LeaseDurationType", + "modelAsString": false + } + }, + "x-ms-lease-state": { + "x-ms-client-name": "LeaseState", + "description": "Lease state of the blob.", + "type": "string", + "enum": [ + "available", + "leased", + "expired", + "breaking", + "broken" + ], + "x-ms-enum": { + "name": "LeaseStateType", + "modelAsString": false + } + }, + "x-ms-lease-status": { + "x-ms-client-name": "LeaseStatus", + "description": "The current lease status of the blob.", + "type": "string", + "enum": [ + "locked", + "unlocked" + ], + "x-ms-enum": { + "name": "LeaseStatusType", + "modelAsString": false + } + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + }, + "x-ms-blob-public-access": { + "x-ms-client-name": "BlobPublicAccess", + "description": "Indicated whether data in the container may be accessed publicly and the level of access", + "type": "string", + "enum": [ + "container", + "blob" + ], + "x-ms-enum": { + "name": "PublicAccessType", + "modelAsString": true + } + }, + "x-ms-has-immutability-policy": { + "x-ms-client-name": "HasImmutabilityPolicy", + "description": "Indicates whether the container has an immutability policy set on it.", + "type": "boolean" + }, + "x-ms-has-legal-hold": { + "x-ms-client-name": "HasLegalHold", + "description": "Indicates whether the container has a legal hold.", + "type": "boolean" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "delete": { + "tags": [ + "container" + ], + "operationId": "Container_Delete", + "description": "operation marks the specified container for deletion. The container and any blobs contained within it are later deleted during garbage collection", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/LeaseIdOptional" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/IfUnmodifiedSince" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "202": { + "description": "Accepted", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "restype", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "container" + ] + } + ] + }, + "/{containerName}?restype=container&comp=metadata": { + "put": { + "tags": [ + "container" + ], + "operationId": "Container_SetMetadata", + "description": "operation sets one or more user-defined name-value pairs for the specified container.", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/LeaseIdOptional" + }, + { + "$ref": "#/parameters/Metadata" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the container was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "restype", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "container" + ] + }, + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "metadata" + ] + } + ] + }, + "/{containerName}?restype=container&comp=acl": { + "get": { + "tags": [ + "container" + ], + "operationId": "Container_GetAccessPolicy", + "description": "gets the permissions for the specified container. The permissions indicate whether container data may be accessed publicly.", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/LeaseIdOptional" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "x-ms-blob-public-access": { + "x-ms-client-name": "BlobPublicAccess", + "description": "Indicated whether data in the container may be accessed publicly and the level of access", + "type": "string", + "enum": [ + "container", + "blob" + ], + "x-ms-enum": { + "name": "PublicAccessType", + "modelAsString": true + } + }, + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the container was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + }, + "schema": { + "$ref": "#/definitions/SignedIdentifiers" + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "put": { + "tags": [ + "container" + ], + "operationId": "Container_SetAccessPolicy", + "description": "sets the permissions for the specified container. The permissions indicate whether blobs in a container may be accessed publicly.", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/ContainerAcl" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/LeaseIdOptional" + }, + { + "$ref": "#/parameters/BlobPublicAccess" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/IfUnmodifiedSince" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "Success.", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the container was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "restype", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "container" + ] + }, + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "acl" + ] + } + ] + }, + "/{containerName}?comp=lease&restype=container&acquire": { + "put": { + "tags": [ + "container" + ], + "operationId": "Container_AcquireLease", + "description": "[Update] establishes and manages a lock on a container for delete operations. The lock duration can be 15 to 60 seconds, or can be infinite", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/LeaseDuration" + }, + { + "$ref": "#/parameters/ProposedLeaseIdOptional" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/IfUnmodifiedSince" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "201": { + "description": "The Acquire operation completed successfully.", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the container was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "x-ms-lease-id": { + "x-ms-client-name": "LeaseId", + "type": "string", + "description": "Uniquely identifies a container's lease" + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "lease" + ] + }, + { + "name": "restype", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "container" + ] + }, + { + "name": "x-ms-lease-action", + "x-ms-client-name": "action", + "in": "header", + "required": true, + "type": "string", + "enum": [ + "acquire" + ], + "x-ms-enum": { + "name": "LeaseAction", + "modelAsString": false + }, + "x-ms-parameter-location": "method", + "description": "Describes what lease action to take." + } + ] + }, + "/{containerName}?comp=lease&restype=container&release": { + "put": { + "tags": [ + "container" + ], + "operationId": "Container_ReleaseLease", + "description": "[Update] establishes and manages a lock on a container for delete operations. The lock duration can be 15 to 60 seconds, or can be infinite", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/LeaseIdRequired" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/IfUnmodifiedSince" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "The Release operation completed successfully.", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the container was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "lease" + ] + }, + { + "name": "restype", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "container" + ] + }, + { + "name": "x-ms-lease-action", + "x-ms-client-name": "action", + "in": "header", + "required": true, + "type": "string", + "enum": [ + "release" + ], + "x-ms-enum": { + "name": "LeaseAction", + "modelAsString": false + }, + "x-ms-parameter-location": "method", + "description": "Describes what lease action to take." + } + ] + }, + "/{containerName}?comp=lease&restype=container&renew": { + "put": { + "tags": [ + "container" + ], + "operationId": "Container_RenewLease", + "description": "[Update] establishes and manages a lock on a container for delete operations. The lock duration can be 15 to 60 seconds, or can be infinite", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/LeaseIdRequired" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/IfUnmodifiedSince" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "The Renew operation completed successfully.", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the container was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "x-ms-lease-id": { + "x-ms-client-name": "LeaseId", + "type": "string", + "description": "Uniquely identifies a container's lease" + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "lease" + ] + }, + { + "name": "restype", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "container" + ] + }, + { + "name": "x-ms-lease-action", + "x-ms-client-name": "action", + "in": "header", + "required": true, + "type": "string", + "enum": [ + "renew" + ], + "x-ms-enum": { + "name": "LeaseAction", + "modelAsString": false + }, + "x-ms-parameter-location": "method", + "description": "Describes what lease action to take." + } + ] + }, + "/{containerName}?comp=lease&restype=container&break": { + "put": { + "tags": [ + "container" + ], + "operationId": "Container_BreakLease", + "description": "[Update] establishes and manages a lock on a container for delete operations. The lock duration can be 15 to 60 seconds, or can be infinite", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/LeaseBreakPeriod" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/IfUnmodifiedSince" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "202": { + "description": "The Break operation completed successfully.", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the container was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "x-ms-lease-time": { + "x-ms-client-name": "LeaseTime", + "type": "integer", + "description": "Approximate time remaining in the lease period, in seconds." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "lease" + ] + }, + { + "name": "restype", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "container" + ] + }, + { + "name": "x-ms-lease-action", + "x-ms-client-name": "action", + "in": "header", + "required": true, + "type": "string", + "enum": [ + "break" + ], + "x-ms-enum": { + "name": "LeaseAction", + "modelAsString": false + }, + "x-ms-parameter-location": "method", + "description": "Describes what lease action to take." + } + ] + }, + "/{containerName}?comp=lease&restype=container&change": { + "put": { + "tags": [ + "container" + ], + "operationId": "Container_ChangeLease", + "description": "[Update] establishes and manages a lock on a container for delete operations. The lock duration can be 15 to 60 seconds, or can be infinite", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/LeaseIdRequired" + }, + { + "$ref": "#/parameters/ProposedLeaseIdRequired" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/IfUnmodifiedSince" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "The Change operation completed successfully.", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the container was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "x-ms-lease-id": { + "x-ms-client-name": "LeaseId", + "type": "string", + "description": "Uniquely identifies a container's lease" + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "lease" + ] + }, + { + "name": "restype", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "container" + ] + }, + { + "name": "x-ms-lease-action", + "x-ms-client-name": "action", + "in": "header", + "required": true, + "type": "string", + "enum": [ + "change" + ], + "x-ms-enum": { + "name": "LeaseAction", + "modelAsString": false + }, + "x-ms-parameter-location": "method", + "description": "Describes what lease action to take." + } + ] + }, + "/{containerName}?restype=container&comp=list&flat": { + "get": { + "tags": [ + "containers" + ], + "operationId": "Container_ListBlobFlatSegment", + "description": "[Update] The List Blobs operation returns a list of the blobs under the specified container", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Prefix" + }, + { + "$ref": "#/parameters/Marker" + }, + { + "$ref": "#/parameters/MaxResults" + }, + { + "$ref": "#/parameters/ListBlobsInclude" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "Success.", + "headers": { + "Content-Type": { + "type": "string", + "description": "The media type of the body of the response. For List Blobs this is 'application/xml'" + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + }, + "schema": { + "$ref": "#/definitions/ListBlobsFlatSegmentResponse" + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "NextMarker" + } + }, + "parameters": [ + { + "name": "restype", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "container" + ] + }, + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "list" + ] + } + ] + }, + "/{containerName}?restype=container&comp=list&hierarchy": { + "get": { + "tags": [ + "containers" + ], + "operationId": "Container_ListBlobHierarchySegment", + "description": "[Update] The List Blobs operation returns a list of the blobs under the specified container", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Prefix" + }, + { + "$ref": "#/parameters/Delimiter" + }, + { + "$ref": "#/parameters/Marker" + }, + { + "$ref": "#/parameters/MaxResults" + }, + { + "$ref": "#/parameters/ListBlobsInclude" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "Success.", + "headers": { + "Content-Type": { + "type": "string", + "description": "The media type of the body of the response. For List Blobs this is 'application/xml'" + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + }, + "schema": { + "$ref": "#/definitions/ListBlobsHierarchySegmentResponse" + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "NextMarker" + } + }, + "parameters": [ + { + "name": "restype", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "container" + ] + }, + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "list" + ] + } + ] + }, + "/{containerName}?restype=account&comp=properties": { + "get": { + "tags": [ + "container" + ], + "operationId": "Container_GetAccountInfo", + "description": "Returns the sku name and account kind ", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Success (OK)", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + }, + "x-ms-sku-name": { + "x-ms-client-name": "SkuName", + "type": "string", + "enum": [ + "Standard_LRS", + "Standard_GRS", + "Standard_RAGRS", + "Standard_ZRS", + "Premium_LRS" + ], + "x-ms-enum": { + "name": "SkuName", + "modelAsString": false + }, + "description": "Identifies the sku name of the account" + }, + "x-ms-account-kind": { + "x-ms-client-name": "AccountKind", + "type": "string", + "enum": [ + "Storage", + "BlobStorage", + "StorageV2" + ], + "x-ms-enum": { + "name": "AccountKind", + "modelAsString": false + }, + "description": "Identifies the account kind" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "restype", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "account" + ] + }, + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "properties" + ] + } + ] + }, + "/{containerName}/{blob}": { + "get": { + "tags": [ + "blob" + ], + "operationId": "Blob_Download", + "description": "The Download operation reads or downloads a blob from the system, including its metadata and properties. You can also call Download to read a snapshot or verison.", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Blob" + }, + { + "$ref": "#/parameters/Snapshot" + }, + { + "$ref": "#/parameters/VersionId" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/Range" + }, + { + "$ref": "#/parameters/LeaseIdOptional" + }, + { + "$ref": "#/parameters/GetRangeContentMD5" + }, + { + "$ref": "#/parameters/EncryptionKey" + }, + { + "$ref": "#/parameters/EncryptionKeySha256" + }, + { + "$ref": "#/parameters/EncryptionAlgorithm" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/IfUnmodifiedSince" + }, + { + "$ref": "#/parameters/IfMatch" + }, + { + "$ref": "#/parameters/IfNoneMatch" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "Returns the content of the entire blob.", + "headers": { + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the container was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "x-ms-meta": { + "type": "string", + "x-ms-client-name": "Metadata", + "x-ms-header-collection-prefix": "x-ms-meta-" + }, + "Content-Length": { + "type": "integer", + "format": "int64", + "description": "The number of bytes present in the response body." + }, + "Content-Type": { + "type": "string", + "description": "The media type of the body of the response. For Download Blob this is 'application/octet-stream'" + }, + "Content-Range": { + "type": "string", + "description": "Indicates the range of bytes returned in the event that the client requested a subset of the blob by setting the 'Range' request header." + }, + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Content-MD5": { + "type": "string", + "format": "byte", + "description": "If the blob has an MD5 hash and this operation is to read the full blob, this response header is returned so that the client can check for message content integrity." + }, + "Content-Encoding": { + "type": "string", + "description": "This header returns the value that was specified for the Content-Encoding request header" + }, + "Cache-Control": { + "type": "string", + "description": "This header is returned if it was previously specified for the blob." + }, + "Content-Disposition": { + "type": "string", + "description": "This header returns the value that was specified for the 'x-ms-blob-content-disposition' header. The Content-Disposition response header field conveys additional information about how to process the response payload, and also can be used to attach additional metadata. For example, if set to attachment, it indicates that the user-agent should not display the response, but instead show a Save As dialog with a filename other than the blob name specified." + }, + "Content-Language": { + "type": "string", + "description": "This header returns the value that was specified for the Content-Language request header." + }, + "x-ms-blob-sequence-number": { + "x-ms-client-name": "BlobSequenceNumber", + "type": "integer", + "format": "int64", + "description": "The current sequence number for a page blob. This header is not returned for block blobs or append blobs" + }, + "x-ms-blob-type": { + "x-ms-client-name": "BlobType", + "description": "The blob's type.", + "type": "string", + "enum": [ + "BlockBlob", + "PageBlob", + "AppendBlob" + ], + "x-ms-enum": { + "name": "BlobType", + "modelAsString": false + } + }, + "x-ms-copy-completion-time": { + "x-ms-client-name": "CopyCompletionTime", + "type": "string", + "format": "date-time-rfc1123", + "description": "Conclusion time of the last attempted Copy Blob operation where this blob was the destination blob. This value can specify the time of a completed, aborted, or failed copy attempt. This header does not appear if a copy is pending, if this blob has never been the destination in a Copy Blob operation, or if this blob has been modified after a concluded Copy Blob operation using Set Blob Properties, Put Blob, or Put Block List." + }, + "x-ms-copy-status-description": { + "x-ms-client-name": "CopyStatusDescription", + "type": "string", + "description": "Only appears when x-ms-copy-status is failed or pending. Describes the cause of the last fatal or non-fatal copy operation failure. This header does not appear if this blob has never been the destination in a Copy Blob operation, or if this blob has been modified after a concluded Copy Blob operation using Set Blob Properties, Put Blob, or Put Block List" + }, + "x-ms-copy-id": { + "x-ms-client-name": "CopyId", + "type": "string", + "description": "String identifier for this copy operation. Use with Get Blob Properties to check the status of this copy operation, or pass to Abort Copy Blob to abort a pending copy." + }, + "x-ms-copy-progress": { + "x-ms-client-name": "CopyProgress", + "type": "string", + "description": "Contains the number of bytes copied and the total bytes in the source in the last attempted Copy Blob operation where this blob was the destination blob. Can show between 0 and Content-Length bytes copied. This header does not appear if this blob has never been the destination in a Copy Blob operation, or if this blob has been modified after a concluded Copy Blob operation using Set Blob Properties, Put Blob, or Put Block List" + }, + "x-ms-copy-source": { + "x-ms-client-name": "CopySource", + "type": "string", + "description": "URL up to 2 KB in length that specifies the source blob or file used in the last attempted Copy Blob operation where this blob was the destination blob. This header does not appear if this blob has never been the destination in a Copy Blob operation, or if this blob has been modified after a concluded Copy Blob operation using Set Blob Properties, Put Blob, or Put Block List." + }, + "x-ms-copy-status": { + "x-ms-client-name": "CopyStatus", + "description": "State of the copy operation identified by x-ms-copy-id.", + "type": "string", + "enum": [ + "pending", + "success", + "aborted", + "failed" + ], + "x-ms-enum": { + "name": "CopyStatusType", + "modelAsString": false + } + }, + "x-ms-lease-duration": { + "x-ms-client-name": "LeaseDuration", + "description": "When a blob is leased, specifies whether the lease is of infinite or fixed duration.", + "type": "string", + "enum": [ + "infinite", + "fixed" + ], + "x-ms-enum": { + "name": "LeaseDurationType", + "modelAsString": false + } + }, + "x-ms-lease-state": { + "x-ms-client-name": "LeaseState", + "description": "Lease state of the blob.", + "type": "string", + "enum": [ + "available", + "leased", + "expired", + "breaking", + "broken" + ], + "x-ms-enum": { + "name": "LeaseStateType", + "modelAsString": false + } + }, + "x-ms-lease-status": { + "x-ms-client-name": "LeaseStatus", + "description": "The current lease status of the blob.", + "type": "string", + "enum": [ + "locked", + "unlocked" + ], + "x-ms-enum": { + "name": "LeaseStatusType", + "modelAsString": false + } + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Accept-Ranges": { + "type": "string", + "description": "Indicates that the service supports requests for partial blob content." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + }, + "x-ms-blob-committed-block-count": { + "x-ms-client-name": "BlobCommittedBlockCount", + "type": "integer", + "description": "The number of committed blocks present in the blob. This header is returned only for append blobs." + }, + "x-ms-server-encrypted": { + "x-ms-client-name": "IsServerEncrypted", + "type": "boolean", + "description": "The value of this header is set to true if the blob data and application metadata are completely encrypted using the specified algorithm. Otherwise, the value is set to false (when the blob is unencrypted, or if only parts of the blob/application metadata are encrypted)." + }, + "x-ms-encryption-key-sha256": { + "x-ms-client-name": "EncryptionKeySha256", + "type": "string", + "description": "The SHA-256 hash of the encryption key used to encrypt the blob. This header is only returned when the blob was encrypted with a customer-provided key." + }, + "x-ms-blob-content-md5": { + "x-ms-client-name": "BlobContentMD5", + "type": "string", + "format": "byte", + "description": "If the blob has a MD5 hash, and if request contains range header (Range or x-ms-range), this response header is returned with the value of the whole blob's MD5 value. This value may or may not be equal to the value returned in Content-MD5 header, with the latter calculated from the requested range" + } + }, + "schema": { + "type": "object", + "format": "file" + } + }, + "206": { + "description": "Returns the content of a specified range of the blob.", + "headers": { + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the container was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "x-ms-meta": { + "type": "string", + "x-ms-client-name": "Metadata", + "x-ms-header-collection-prefix": "x-ms-meta-" + }, + "Content-Length": { + "type": "integer", + "format": "int64", + "description": "The number of bytes present in the response body." + }, + "Content-Type": { + "type": "string", + "description": "The media type of the body of the response. For Download Blob this is 'application/octet-stream'" + }, + "Content-Range": { + "type": "string", + "description": "Indicates the range of bytes returned in the event that the client requested a subset of the blob by setting the 'Range' request header." + }, + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Content-MD5": { + "type": "string", + "format": "byte", + "description": "If the blob has an MD5 hash and this operation is to read the full blob, this response header is returned so that the client can check for message content integrity." + }, + "Content-Encoding": { + "type": "string", + "description": "This header returns the value that was specified for the Content-Encoding request header" + }, + "Cache-Control": { + "type": "string", + "description": "This header is returned if it was previously specified for the blob." + }, + "Content-Disposition": { + "type": "string", + "description": "This header returns the value that was specified for the 'x-ms-blob-content-disposition' header. The Content-Disposition response header field conveys additional information about how to process the response payload, and also can be used to attach additional metadata. For example, if set to attachment, it indicates that the user-agent should not display the response, but instead show a Save As dialog with a filename other than the blob name specified." + }, + "Content-Language": { + "type": "string", + "description": "This header returns the value that was specified for the Content-Language request header." + }, + "x-ms-blob-sequence-number": { + "x-ms-client-name": "BlobSequenceNumber", + "type": "integer", + "format": "int64", + "description": "The current sequence number for a page blob. This header is not returned for block blobs or append blobs" + }, + "x-ms-blob-type": { + "x-ms-client-name": "BlobType", + "description": "The blob's type.", + "type": "string", + "enum": [ + "BlockBlob", + "PageBlob", + "AppendBlob" + ], + "x-ms-enum": { + "name": "BlobType", + "modelAsString": false + } + }, + "x-ms-copy-completion-time": { + "x-ms-client-name": "CopyCompletionTime", + "type": "string", + "format": "date-time-rfc1123", + "description": "Conclusion time of the last attempted Copy Blob operation where this blob was the destination blob. This value can specify the time of a completed, aborted, or failed copy attempt. This header does not appear if a copy is pending, if this blob has never been the destination in a Copy Blob operation, or if this blob has been modified after a concluded Copy Blob operation using Set Blob Properties, Put Blob, or Put Block List." + }, + "x-ms-copy-status-description": { + "x-ms-client-name": "CopyStatusDescription", + "type": "string", + "description": "Only appears when x-ms-copy-status is failed or pending. Describes the cause of the last fatal or non-fatal copy operation failure. This header does not appear if this blob has never been the destination in a Copy Blob operation, or if this blob has been modified after a concluded Copy Blob operation using Set Blob Properties, Put Blob, or Put Block List" + }, + "x-ms-copy-id": { + "x-ms-client-name": "CopyId", + "type": "string", + "description": "String identifier for this copy operation. Use with Get Blob Properties to check the status of this copy operation, or pass to Abort Copy Blob to abort a pending copy." + }, + "x-ms-copy-progress": { + "x-ms-client-name": "CopyProgress", + "type": "string", + "description": "Contains the number of bytes copied and the total bytes in the source in the last attempted Copy Blob operation where this blob was the destination blob. Can show between 0 and Content-Length bytes copied. This header does not appear if this blob has never been the destination in a Copy Blob operation, or if this blob has been modified after a concluded Copy Blob operation using Set Blob Properties, Put Blob, or Put Block List" + }, + "x-ms-copy-source": { + "x-ms-client-name": "CopySource", + "type": "string", + "description": "URL up to 2 KB in length that specifies the source blob or file used in the last attempted Copy Blob operation where this blob was the destination blob. This header does not appear if this blob has never been the destination in a Copy Blob operation, or if this blob has been modified after a concluded Copy Blob operation using Set Blob Properties, Put Blob, or Put Block List." + }, + "x-ms-copy-status": { + "x-ms-client-name": "CopyStatus", + "description": "State of the copy operation identified by x-ms-copy-id.", + "type": "string", + "enum": [ + "pending", + "success", + "aborted", + "failed" + ], + "x-ms-enum": { + "name": "CopyStatusType", + "modelAsString": false + } + }, + "x-ms-lease-duration": { + "x-ms-client-name": "LeaseDuration", + "description": "When a blob is leased, specifies whether the lease is of infinite or fixed duration.", + "type": "string", + "enum": [ + "infinite", + "fixed" + ], + "x-ms-enum": { + "name": "LeaseDurationType", + "modelAsString": false + } + }, + "x-ms-lease-state": { + "x-ms-client-name": "LeaseState", + "description": "Lease state of the blob.", + "type": "string", + "enum": [ + "available", + "leased", + "expired", + "breaking", + "broken" + ], + "x-ms-enum": { + "name": "LeaseStateType", + "modelAsString": false + } + }, + "x-ms-lease-status": { + "x-ms-client-name": "LeaseStatus", + "description": "The current lease status of the blob.", + "type": "string", + "enum": [ + "locked", + "unlocked" + ], + "x-ms-enum": { + "name": "LeaseStatusType", + "modelAsString": false + } + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Accept-Ranges": { + "type": "string", + "description": "Indicates that the service supports requests for partial blob content." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + }, + "x-ms-blob-committed-block-count": { + "x-ms-client-name": "BlobCommittedBlockCount", + "type": "integer", + "description": "The number of committed blocks present in the blob. This header is returned only for append blobs." + }, + "x-ms-server-encrypted": { + "x-ms-client-name": "IsServerEncrypted", + "type": "boolean", + "description": "The value of this header is set to true if the blob data and application metadata are completely encrypted using the specified algorithm. Otherwise, the value is set to false (when the blob is unencrypted, or if only parts of the blob/application metadata are encrypted)." + }, + "x-ms-blob-content-md5": { + "x-ms-client-name": "BlobContentMD5", + "type": "string", + "format": "byte", + "description": "If the blob has a MD5 hash, and if request contains range header (Range or x-ms-range), this response header is returned with the value of the whole blob's MD5 value. This value may or may not be equal to the value returned in Content-MD5 header, with the latter calculated from the requested range" + } + }, + "schema": { + "type": "object", + "format": "file" + } + }, + "304": { + "description": "The condition specified using HTTP conditional header(s) is not met.", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "head": { + "tags": [ + "blob" + ], + "operationId": "Blob_GetProperties", + "description": "The Get Properties operation returns all user-defined metadata, standard HTTP properties, and system properties for the blob. It does not return the content of the blob.", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Blob" + }, + { + "$ref": "#/parameters/Snapshot" + }, + { + "$ref": "#/parameters/VersionId" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/LeaseIdOptional" + }, + { + "$ref": "#/parameters/EncryptionKey" + }, + { + "$ref": "#/parameters/EncryptionKeySha256" + }, + { + "$ref": "#/parameters/EncryptionAlgorithm" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/IfUnmodifiedSince" + }, + { + "$ref": "#/parameters/IfMatch" + }, + { + "$ref": "#/parameters/IfNoneMatch" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "Returns the properties of the blob.", + "headers": { + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the blob was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "x-ms-creation-time": { + "x-ms-client-name": "CreationTime", + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the blob was created." + }, + "x-ms-meta": { + "type": "string", + "x-ms-client-name": "Metadata", + "x-ms-header-collection-prefix": "x-ms-meta-" + }, + "x-ms-blob-type": { + "x-ms-client-name": "BlobType", + "description": "The blob's type.", + "type": "string", + "enum": [ + "BlockBlob", + "PageBlob", + "AppendBlob" + ], + "x-ms-enum": { + "name": "BlobType", + "modelAsString": false + } + }, + "x-ms-copy-completion-time": { + "x-ms-client-name": "CopyCompletionTime", + "type": "string", + "format": "date-time-rfc1123", + "description": "Conclusion time of the last attempted Copy Blob operation where this blob was the destination blob. This value can specify the time of a completed, aborted, or failed copy attempt. This header does not appear if a copy is pending, if this blob has never been the destination in a Copy Blob operation, or if this blob has been modified after a concluded Copy Blob operation using Set Blob Properties, Put Blob, or Put Block List." + }, + "x-ms-copy-status-description": { + "x-ms-client-name": "CopyStatusDescription", + "type": "string", + "description": "Only appears when x-ms-copy-status is failed or pending. Describes the cause of the last fatal or non-fatal copy operation failure. This header does not appear if this blob has never been the destination in a Copy Blob operation, or if this blob has been modified after a concluded Copy Blob operation using Set Blob Properties, Put Blob, or Put Block List" + }, + "x-ms-copy-id": { + "x-ms-client-name": "CopyId", + "type": "string", + "description": "String identifier for this copy operation. Use with Get Blob Properties to check the status of this copy operation, or pass to Abort Copy Blob to abort a pending copy." + }, + "x-ms-copy-progress": { + "x-ms-client-name": "CopyProgress", + "type": "string", + "description": "Contains the number of bytes copied and the total bytes in the source in the last attempted Copy Blob operation where this blob was the destination blob. Can show between 0 and Content-Length bytes copied. This header does not appear if this blob has never been the destination in a Copy Blob operation, or if this blob has been modified after a concluded Copy Blob operation using Set Blob Properties, Put Blob, or Put Block List" + }, + "x-ms-copy-source": { + "x-ms-client-name": "CopySource", + "type": "string", + "description": "URL up to 2 KB in length that specifies the source blob or file used in the last attempted Copy Blob operation where this blob was the destination blob. This header does not appear if this blob has never been the destination in a Copy Blob operation, or if this blob has been modified after a concluded Copy Blob operation using Set Blob Properties, Put Blob, or Put Block List." + }, + "x-ms-copy-status": { + "x-ms-client-name": "CopyStatus", + "description": "State of the copy operation identified by x-ms-copy-id.", + "type": "string", + "enum": [ + "pending", + "success", + "aborted", + "failed" + ], + "x-ms-enum": { + "name": "CopyStatusType", + "modelAsString": false + } + }, + "x-ms-incremental-copy": { + "x-ms-client-name": "IsIncrementalCopy", + "type": "boolean", + "description": "Included if the blob is incremental copy blob." + }, + "x-ms-copy-destination-snapshot": { + "x-ms-client-name": "DestinationSnapshot", + "type": "string", + "description": "Included if the blob is incremental copy blob or incremental copy snapshot, if x-ms-copy-status is success. Snapshot time of the last successful incremental copy snapshot for this blob." + }, + "x-ms-lease-duration": { + "x-ms-client-name": "LeaseDuration", + "description": "When a blob is leased, specifies whether the lease is of infinite or fixed duration.", + "type": "string", + "enum": [ + "infinite", + "fixed" + ], + "x-ms-enum": { + "name": "LeaseDurationType", + "modelAsString": false + } + }, + "x-ms-lease-state": { + "x-ms-client-name": "LeaseState", + "description": "Lease state of the blob.", + "type": "string", + "enum": [ + "available", + "leased", + "expired", + "breaking", + "broken" + ], + "x-ms-enum": { + "name": "LeaseStateType", + "modelAsString": false + } + }, + "x-ms-lease-status": { + "x-ms-client-name": "LeaseStatus", + "description": "The current lease status of the blob.", + "type": "string", + "enum": [ + "locked", + "unlocked" + ], + "x-ms-enum": { + "name": "LeaseStatusType", + "modelAsString": false + } + }, + "Content-Length": { + "type": "integer", + "format": "int64", + "description": "The number of bytes present in the response body." + }, + "Content-Type": { + "type": "string", + "description": "The content type specified for the blob. The default content type is 'application/octet-stream'" + }, + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Content-MD5": { + "type": "string", + "format": "byte", + "description": "If the blob has an MD5 hash and this operation is to read the full blob, this response header is returned so that the client can check for message content integrity." + }, + "Content-Encoding": { + "type": "string", + "description": "This header returns the value that was specified for the Content-Encoding request header" + }, + "Content-Disposition": { + "type": "string", + "description": "This header returns the value that was specified for the 'x-ms-blob-content-disposition' header. The Content-Disposition response header field conveys additional information about how to process the response payload, and also can be used to attach additional metadata. For example, if set to attachment, it indicates that the user-agent should not display the response, but instead show a Save As dialog with a filename other than the blob name specified." + }, + "Content-Language": { + "type": "string", + "description": "This header returns the value that was specified for the Content-Language request header." + }, + "Cache-Control": { + "type": "string", + "description": "This header is returned if it was previously specified for the blob." + }, + "x-ms-blob-sequence-number": { + "x-ms-client-name": "BlobSequenceNumber", + "type": "integer", + "format": "int64", + "description": "The current sequence number for a page blob. This header is not returned for block blobs or append blobs" + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + }, + "Accept-Ranges": { + "type": "string", + "description": "Indicates that the service supports requests for partial blob content." + }, + "x-ms-blob-committed-block-count": { + "x-ms-client-name": "BlobCommittedBlockCount", + "type": "integer", + "description": "The number of committed blocks present in the blob. This header is returned only for append blobs." + }, + "x-ms-server-encrypted": { + "x-ms-client-name": "IsServerEncrypted", + "type": "boolean", + "description": "The value of this header is set to true if the blob data and application metadata are completely encrypted using the specified algorithm. Otherwise, the value is set to false (when the blob is unencrypted, or if only parts of the blob/application metadata are encrypted)." + }, + "x-ms-encryption-key-sha256": { + "x-ms-client-name": "EncryptionKeySha256", + "type": "string", + "description": "The SHA-256 hash of the encryption key used to encrypt the metadata. This header is only returned when the metadata was encrypted with a customer-provided key." + }, + "x-ms-access-tier": { + "x-ms-client-name": "AccessTier", + "type": "string", + "description": "The tier of page blob on a premium storage account or tier of block blob on blob storage LRS accounts. For a list of allowed premium page blob tiers, see https://docs.microsoft.com/en-us/azure/virtual-machines/windows/premium-storage#features. For blob storage LRS accounts, valid values are Hot/Cool/Archive." + }, + "x-ms-access-tier-inferred": { + "x-ms-client-name": "AccessTierInferred", + "type": "boolean", + "description": "For page blobs on a premium storage account only. If the access tier is not explicitly set on the blob, the tier is inferred based on its content length and this header will be returned with true value." + }, + "x-ms-archive-status": { + "x-ms-client-name": "ArchiveStatus", + "type": "string", + "description": "For blob storage LRS accounts, valid values are rehydrate-pending-to-hot/rehydrate-pending-to-cool. If the blob is being rehydrated and is not complete then this header is returned indicating that rehydrate is pending and also tells the destination tier." + }, + "x-ms-access-tier-change-time": { + "x-ms-client-name": "AccessTierChangeTime", + "type": "string", + "format": "date-time-rfc1123", + "description": "The time the tier was changed on the object. This is only returned if the tier on the block blob was ever set." + } + } + }, + "304": { + "description": "The condition specified using HTTP conditional header(s) is not met.", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "delete": { + "tags": [ + "blob" + ], + "operationId": "Blob_Delete", + "description": "If the storage account's soft delete feature is disabled then, when a blob is deleted, it is permanently removed from the storage account. If the storage account's soft delete feature is enabled, then, when a blob is deleted, it is marked for deletion and becomes inaccessible immediately. However, the blob service retains the blob or snapshot for the number of days specified by the DeleteRetentionPolicy section of [Storage service properties] (Set-Blob-Service-Properties.md). After the specified number of days has passed, the blob's data is permanently removed from the storage account. Note that you continue to be charged for the soft-deleted blob's storage until it is permanently removed. Use the List Blobs API and specify the \"include=deleted\" query parameter to discover which blobs and snapshots have been soft deleted. You can then use the Undelete Blob API to restore a soft-deleted blob. All other operations on a soft-deleted blob or snapshot causes the service to return an HTTP status code of 404 (ResourceNotFound). If the storage account's automatic snapshot feature is enabled, then, when a blob is deleted, an automatic snapshot is created. The blob becomes inaccessible immediately. All other operations on the blob causes the service to return an HTTP status code of 404 (ResourceNotFound). You can access automatic snapshot using snapshot timestamp or version id. You can restore the blob by calling Put or Copy Blob API with automatic snapshot as source. Deleting automatic snapshot requires shared key or special SAS/RBAC permissions.", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Blob" + }, + { + "$ref": "#/parameters/Snapshot" + }, + { + "$ref": "#/parameters/VersionId" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/LeaseIdOptional" + }, + { + "$ref": "#/parameters/DeleteSnapshots" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/IfUnmodifiedSince" + }, + { + "$ref": "#/parameters/IfMatch" + }, + { + "$ref": "#/parameters/IfNoneMatch" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "202": { + "description": "The delete request was accepted and the blob will be deleted.", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + } + }, + "/{containerName}/{blob}?PageBlob": { + "put": { + "tags": [ + "blob" + ], + "operationId": "PageBlob_Create", + "description": "The Create operation creates a new page blob.", + "consumes": [ + "application/octet-stream" + ], + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Blob" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ContentLength" + }, + { + "$ref": "#/parameters/BlobContentType" + }, + { + "$ref": "#/parameters/BlobContentEncoding" + }, + { + "$ref": "#/parameters/BlobContentLanguage" + }, + { + "$ref": "#/parameters/BlobContentMD5" + }, + { + "$ref": "#/parameters/BlobCacheControl" + }, + { + "$ref": "#/parameters/Metadata" + }, + { + "$ref": "#/parameters/LeaseIdOptional" + }, + { + "$ref": "#/parameters/BlobContentDisposition" + }, + { + "$ref": "#/parameters/EncryptionKey" + }, + { + "$ref": "#/parameters/EncryptionKeySha256" + }, + { + "$ref": "#/parameters/EncryptionAlgorithm" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/IfUnmodifiedSince" + }, + { + "$ref": "#/parameters/IfMatch" + }, + { + "$ref": "#/parameters/IfNoneMatch" + }, + { + "$ref": "#/parameters/BlobContentLengthRequired" + }, + { + "$ref": "#/parameters/BlobSequenceNumber" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "201": { + "description": "The blob was created.", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the container was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "Content-MD5": { + "type": "string", + "format": "byte", + "description": "If the blob has an MD5 hash and this operation is to read the full blob, this response header is returned so that the client can check for message content integrity." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "x-ms-version-id": { + "x-ms-client-name": "VersionId", + "type": "string", + "description": "UTC date/time value generated by the service that identifies a version of the blob. This header is returned for requests made against version 2018-11-09 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + }, + "x-ms-request-server-encrypted": { + "x-ms-client-name": "IsServerEncrypted", + "type": "boolean", + "description": "The value of this header is set to true if the contents of the request are successfully encrypted using the specified algorithm, and false otherwise." + }, + "x-ms-encryption-key-sha256": { + "x-ms-client-name": "EncryptionKeySha256", + "type": "string", + "description": "The SHA-256 hash of the encryption key used to encrypt the blob. This header is only returned when the blob was encrypted with a customer-provided key." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "x-ms-blob-type", + "x-ms-client-name": "blobType", + "in": "header", + "required": true, + "x-ms-parameter-location": "method", + "description": "Specifies the type of blob to create: block blob, page blob, or append blob.", + "type": "string", + "enum": [ + "PageBlob" + ], + "x-ms-enum": { + "name": "BlobType", + "modelAsString": false + } + } + ] + }, + "/{containerName}/{blob}?AppendBlob": { + "put": { + "tags": [ + "blob" + ], + "operationId": "AppendBlob_Create", + "description": "The Create Append Blob operation creates a new append blob.", + "consumes": [ + "application/octet-stream" + ], + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Blob" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ContentLength" + }, + { + "$ref": "#/parameters/BlobContentType" + }, + { + "$ref": "#/parameters/BlobContentEncoding" + }, + { + "$ref": "#/parameters/BlobContentLanguage" + }, + { + "$ref": "#/parameters/BlobContentMD5" + }, + { + "$ref": "#/parameters/BlobCacheControl" + }, + { + "$ref": "#/parameters/Metadata" + }, + { + "$ref": "#/parameters/LeaseIdOptional" + }, + { + "$ref": "#/parameters/BlobContentDisposition" + }, + { + "$ref": "#/parameters/EncryptionKey" + }, + { + "$ref": "#/parameters/EncryptionKeySha256" + }, + { + "$ref": "#/parameters/EncryptionAlgorithm" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/IfUnmodifiedSince" + }, + { + "$ref": "#/parameters/IfMatch" + }, + { + "$ref": "#/parameters/IfNoneMatch" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "201": { + "description": "The blob was created.", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the container was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "Content-MD5": { + "type": "string", + "format": "byte", + "description": "If the blob has an MD5 hash and this operation is to read the full blob, this response header is returned so that the client can check for message content integrity." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "x-ms-version-id": { + "x-ms-client-name": "VersionId", + "type": "string", + "description": "UTC date/time value generated by the service that identifies a version of the blob. This header is returned for requests made against version 2018-11-09 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + }, + "x-ms-request-server-encrypted": { + "x-ms-client-name": "IsServerEncrypted", + "type": "boolean", + "description": "The value of this header is set to true if the contents of the request are successfully encrypted using the specified algorithm, and false otherwise." + }, + "x-ms-encryption-key-sha256": { + "x-ms-client-name": "EncryptionKeySha256", + "type": "string", + "description": "The SHA-256 hash of the encryption key used to encrypt the blob. This header is only returned when the blob was encrypted with a customer-provided key." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "x-ms-blob-type", + "x-ms-client-name": "blobType", + "in": "header", + "required": true, + "x-ms-parameter-location": "method", + "description": "Specifies the type of blob to create: block blob, page blob, or append blob.", + "type": "string", + "enum": [ + "AppendBlob" + ], + "x-ms-enum": { + "name": "BlobType", + "modelAsString": false + } + } + ] + }, + "/{containerName}/{blob}?BlockBlob": { + "put": { + "tags": [ + "blob" + ], + "operationId": "BlockBlob_Upload", + "description": "The Upload Block Blob operation updates the content of an existing block blob. Updating an existing block blob overwrites any existing metadata on the blob. Partial updates are not supported with Put Blob; the content of the existing blob is overwritten with the content of the new blob. To perform a partial update of the content of a block blob, use the Put Block List operation.", + "consumes": [ + "application/octet-stream" + ], + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Blob" + }, + { + "$ref": "#/parameters/Body" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ContentLength" + }, + { + "$ref": "#/parameters/BlobContentType" + }, + { + "$ref": "#/parameters/BlobContentEncoding" + }, + { + "$ref": "#/parameters/BlobContentLanguage" + }, + { + "$ref": "#/parameters/BlobContentMD5" + }, + { + "$ref": "#/parameters/BlobCacheControl" + }, + { + "$ref": "#/parameters/Metadata" + }, + { + "$ref": "#/parameters/LeaseIdOptional" + }, + { + "$ref": "#/parameters/BlobContentDisposition" + }, + { + "$ref": "#/parameters/EncryptionKey" + }, + { + "$ref": "#/parameters/EncryptionKeySha256" + }, + { + "$ref": "#/parameters/EncryptionAlgorithm" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/IfUnmodifiedSince" + }, + { + "$ref": "#/parameters/IfMatch" + }, + { + "$ref": "#/parameters/IfNoneMatch" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "201": { + "description": "The blob was updated.", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the container was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "Content-MD5": { + "type": "string", + "format": "byte", + "description": "If the blob has an MD5 hash and this operation is to read the full blob, this response header is returned so that the client can check for message content integrity." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "x-ms-version-id": { + "x-ms-client-name": "VersionId", + "type": "string", + "description": "UTC date/time value generated by the service that identifies a version of the blob. This header is returned for requests made against version 2018-11-09 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + }, + "x-ms-request-server-encrypted": { + "x-ms-client-name": "IsServerEncrypted", + "type": "boolean", + "description": "The value of this header is set to true if the contents of the request are successfully encrypted using the specified algorithm, and false otherwise." + }, + "x-ms-encryption-key-sha256": { + "x-ms-client-name": "EncryptionKeySha256", + "type": "string", + "description": "The SHA-256 hash of the encryption key used to encrypt the blob. This header is only returned when the blob was encrypted with a customer-provided key." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "x-ms-blob-type", + "x-ms-client-name": "blobType", + "in": "header", + "required": true, + "x-ms-parameter-location": "method", + "description": "Specifies the type of blob to create: block blob, page blob, or append blob.", + "type": "string", + "enum": [ + "BlockBlob" + ], + "x-ms-enum": { + "name": "BlobType", + "modelAsString": false + } + } + ] + }, + "/{containerName}/{blob}?comp=undelete": { + "put": { + "tags": [ + "blob" + ], + "operationId": "Blob_Undelete", + "description": "Undelete a blob that was previously soft deleted", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Blob" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "The blob was undeleted successfully.", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "undelete" + ] + } + ] + }, + "/{containerName}/{blob}?comp=properties&SetHTTPHeaders": { + "put": { + "tags": [ + "blob" + ], + "operationId": "Blob_SetHTTPHeaders", + "description": "The Set HTTP Headers operation sets system properties on the blob", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Blob" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/BlobCacheControl" + }, + { + "$ref": "#/parameters/BlobContentType" + }, + { + "$ref": "#/parameters/BlobContentMD5" + }, + { + "$ref": "#/parameters/BlobContentEncoding" + }, + { + "$ref": "#/parameters/BlobContentLanguage" + }, + { + "$ref": "#/parameters/LeaseIdOptional" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/IfUnmodifiedSince" + }, + { + "$ref": "#/parameters/IfMatch" + }, + { + "$ref": "#/parameters/IfNoneMatch" + }, + { + "$ref": "#/parameters/BlobContentDisposition" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "The properties were set successfully.", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the container was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "x-ms-blob-sequence-number": { + "x-ms-client-name": "BlobSequenceNumber", + "type": "integer", + "format": "int64", + "description": "The current sequence number for a page blob. This header is not returned for block blobs or append blobs" + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "properties" + ] + } + ] + }, + "/{containerName}/{blob}?comp=metadata": { + "put": { + "tags": [ + "blob" + ], + "operationId": "Blob_SetMetadata", + "description": "The Set Blob Metadata operation sets user-defined metadata for the specified blob as one or more name-value pairs", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Blob" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/Metadata" + }, + { + "$ref": "#/parameters/LeaseIdOptional" + }, + { + "$ref": "#/parameters/EncryptionKey" + }, + { + "$ref": "#/parameters/EncryptionKeySha256" + }, + { + "$ref": "#/parameters/EncryptionAlgorithm" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/IfUnmodifiedSince" + }, + { + "$ref": "#/parameters/IfMatch" + }, + { + "$ref": "#/parameters/IfNoneMatch" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "The metadata was set successfully.", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the container was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + }, + "x-ms-request-server-encrypted": { + "x-ms-client-name": "IsServerEncrypted", + "type": "boolean", + "description": "The value of this header is set to true if the contents of the request are successfully encrypted using the specified algorithm, and false otherwise." + }, + "x-ms-encryption-key-sha256": { + "x-ms-client-name": "EncryptionKeySha256", + "type": "string", + "description": "The SHA-256 hash of the encryption key used to encrypt the metadata. This header is only returned when the metadata was encrypted with a customer-provided key." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "metadata" + ] + } + ] + }, + "/{containerName}/{blob}?comp=lease&acquire": { + "put": { + "tags": [ + "blob" + ], + "operationId": "Blob_AcquireLease", + "description": "[Update] The Lease Blob operation establishes and manages a lock on a blob for write and delete operations", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Blob" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/LeaseDuration" + }, + { + "$ref": "#/parameters/ProposedLeaseIdOptional" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/IfUnmodifiedSince" + }, + { + "$ref": "#/parameters/IfMatch" + }, + { + "$ref": "#/parameters/IfNoneMatch" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "201": { + "description": "The Acquire operation completed successfully.", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the blob was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "x-ms-lease-id": { + "x-ms-client-name": "LeaseId", + "type": "string", + "description": "Uniquely identifies a blobs's lease" + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "lease" + ] + }, + { + "name": "x-ms-lease-action", + "x-ms-client-name": "action", + "in": "header", + "required": true, + "type": "string", + "enum": [ + "acquire" + ], + "x-ms-enum": { + "name": "LeaseAction", + "modelAsString": false + }, + "x-ms-parameter-location": "method", + "description": "Describes what lease action to take." + } + ] + }, + "/{containerName}/{blob}?comp=lease&release": { + "put": { + "tags": [ + "blob" + ], + "operationId": "Blob_ReleaseLease", + "description": "[Update] The Lease Blob operation establishes and manages a lock on a blob for write and delete operations", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Blob" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/LeaseIdRequired" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/IfUnmodifiedSince" + }, + { + "$ref": "#/parameters/IfMatch" + }, + { + "$ref": "#/parameters/IfNoneMatch" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "The Release operation completed successfully.", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the blob was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "lease" + ] + }, + { + "name": "x-ms-lease-action", + "x-ms-client-name": "action", + "in": "header", + "required": true, + "type": "string", + "enum": [ + "release" + ], + "x-ms-enum": { + "name": "LeaseAction", + "modelAsString": false + }, + "x-ms-parameter-location": "method", + "description": "Describes what lease action to take." + } + ] + }, + "/{containerName}/{blob}?comp=lease&renew": { + "put": { + "tags": [ + "blob" + ], + "operationId": "Blob_RenewLease", + "description": "[Update] The Lease Blob operation establishes and manages a lock on a blob for write and delete operations", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Blob" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/LeaseIdRequired" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/IfUnmodifiedSince" + }, + { + "$ref": "#/parameters/IfMatch" + }, + { + "$ref": "#/parameters/IfNoneMatch" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "The Renew operation completed successfully.", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the blob was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "x-ms-lease-id": { + "x-ms-client-name": "LeaseId", + "type": "string", + "description": "Uniquely identifies a blobs's lease" + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "lease" + ] + }, + { + "name": "x-ms-lease-action", + "x-ms-client-name": "action", + "in": "header", + "required": true, + "type": "string", + "enum": [ + "renew" + ], + "x-ms-enum": { + "name": "LeaseAction", + "modelAsString": false + }, + "x-ms-parameter-location": "method", + "description": "Describes what lease action to take." + } + ] + }, + "/{containerName}/{blob}?comp=lease&change": { + "put": { + "tags": [ + "blob" + ], + "operationId": "Blob_ChangeLease", + "description": "[Update] The Lease Blob operation establishes and manages a lock on a blob for write and delete operations", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Blob" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/LeaseIdRequired" + }, + { + "$ref": "#/parameters/ProposedLeaseIdRequired" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/IfUnmodifiedSince" + }, + { + "$ref": "#/parameters/IfMatch" + }, + { + "$ref": "#/parameters/IfNoneMatch" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "The Change operation completed successfully.", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the blob was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-lease-id": { + "x-ms-client-name": "LeaseId", + "type": "string", + "description": "Uniquely identifies a blobs's lease" + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "lease" + ] + }, + { + "name": "x-ms-lease-action", + "x-ms-client-name": "action", + "in": "header", + "required": true, + "type": "string", + "enum": [ + "change" + ], + "x-ms-enum": { + "name": "LeaseAction", + "modelAsString": false + }, + "x-ms-parameter-location": "method", + "description": "Describes what lease action to take." + } + ] + }, + "/{containerName}/{blob}?comp=lease&break": { + "put": { + "tags": [ + "blob" + ], + "operationId": "Blob_BreakLease", + "description": "[Update] The Lease Blob operation establishes and manages a lock on a blob for write and delete operations", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Blob" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/LeaseBreakPeriod" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/IfUnmodifiedSince" + }, + { + "$ref": "#/parameters/IfMatch" + }, + { + "$ref": "#/parameters/IfNoneMatch" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "202": { + "description": "The Break operation completed successfully.", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the blob was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "x-ms-lease-time": { + "x-ms-client-name": "LeaseTime", + "type": "integer", + "description": "Approximate time remaining in the lease period, in seconds." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "lease" + ] + }, + { + "name": "x-ms-lease-action", + "x-ms-client-name": "action", + "in": "header", + "required": true, + "type": "string", + "enum": [ + "break" + ], + "x-ms-enum": { + "name": "LeaseAction", + "modelAsString": false + }, + "x-ms-parameter-location": "method", + "description": "Describes what lease action to take." + } + ] + }, + "/{containerName}/{blob}?comp=snapshot": { + "put": { + "tags": [ + "blob" + ], + "operationId": "Blob_CreateSnapshot", + "description": "The Create Snapshot operation creates a read-only snapshot of a blob", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Blob" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/Metadata" + }, + { + "$ref": "#/parameters/EncryptionKey" + }, + { + "$ref": "#/parameters/EncryptionKeySha256" + }, + { + "$ref": "#/parameters/EncryptionAlgorithm" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/IfUnmodifiedSince" + }, + { + "$ref": "#/parameters/IfMatch" + }, + { + "$ref": "#/parameters/IfNoneMatch" + }, + { + "$ref": "#/parameters/LeaseIdOptional" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "201": { + "description": "The snaptshot was taken successfully.", + "headers": { + "x-ms-snapshot": { + "x-ms-client-name": "Snapshot", + "type": "string", + "description": "Uniquely identifies the snapshot and indicates the snapshot version. It may be used in subsequent requests to access the snapshot" + }, + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the container was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "x-ms-version-id": { + "x-ms-client-name": "VersionId", + "type": "string", + "description": "UTC date/time value generated by the service that identifies the version of the blob. This header is returned for requests made against version 2018-11-09 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + }, + "x-ms-request-server-encrypted": { + "x-ms-client-name": "IsServerEncrypted", + "type": "boolean", + "description": "True if the contents of the request are successfully encrypted using the specified algorithm, and false otherwise. For a snapshot request, this header is set to true when metadata was provided in the request and encrypted with a customer-provided key." + }, + "x-ms-encryption-key-sha256": { + "x-ms-client-name": "EncryptionKeySha256", + "type": "string", + "description": "The SHA-256 hash of the encryption key used to encrypt the source blob. This header is only returned when the blob was encrypted with a customer-provided key." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "snapshot" + ] + } + ] + }, + "/{containerName}/{blob}?comp=copy": { + "put": { + "tags": [ + "blob" + ], + "operationId": "Blob_StartCopyFromURL", + "description": "The Start Copy From URL operation copies a blob or an internet resource to a new blob.", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Blob" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/Metadata" + }, + { + "$ref": "#/parameters/SourceIfModifiedSince" + }, + { + "$ref": "#/parameters/SourceIfUnmodifiedSince" + }, + { + "$ref": "#/parameters/SourceIfMatch" + }, + { + "$ref": "#/parameters/SourceIfNoneMatch" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/IfUnmodifiedSince" + }, + { + "$ref": "#/parameters/IfMatch" + }, + { + "$ref": "#/parameters/IfNoneMatch" + }, + { + "$ref": "#/parameters/CopySource" + }, + { + "$ref": "#/parameters/LeaseIdOptional" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "202": { + "description": "The copy blob has been accepted with the specified copy status.", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the container was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "x-ms-version-id": { + "x-ms-client-name": "VersionId", + "type": "string", + "description": "UTC date/time value generated by the service that identifies the version of the blob. This header is returned for requests made against version 2018-11-09 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + }, + "x-ms-copy-id": { + "x-ms-client-name": "CopyId", + "type": "string", + "description": "String identifier for this copy operation. Use with Get Blob Properties to check the status of this copy operation, or pass to Abort Copy Blob to abort a pending copy." + }, + "x-ms-copy-status": { + "x-ms-client-name": "CopyStatus", + "description": "State of the copy operation identified by x-ms-copy-id.", + "type": "string", + "enum": [ + "pending", + "success", + "aborted", + "failed" + ], + "x-ms-enum": { + "name": "CopyStatusType", + "modelAsString": false + } + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [] + }, + "/{containerName}/{blob}?comp=copy&sync": { + "put": { + "tags": [ + "blob" + ], + "operationId": "Blob_CopyFromURL", + "description": "The Copy From URL operation copies a blob or an internet resource to a new blob. It will not return a response until the copy is complete.", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Blob" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/Metadata" + }, + { + "$ref": "#/parameters/SourceIfModifiedSince" + }, + { + "$ref": "#/parameters/SourceIfUnmodifiedSince" + }, + { + "$ref": "#/parameters/SourceIfMatch" + }, + { + "$ref": "#/parameters/SourceIfNoneMatch" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/IfUnmodifiedSince" + }, + { + "$ref": "#/parameters/IfMatch" + }, + { + "$ref": "#/parameters/IfNoneMatch" + }, + { + "$ref": "#/parameters/CopySource" + }, + { + "$ref": "#/parameters/LeaseIdOptional" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "202": { + "description": "The copy has completed.", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the container was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "x-ms-version-id": { + "x-ms-client-name": "VersionId", + "type": "string", + "description": "UTC date/time value generated by the service that identifies the version of the blob. This header is returned for requests made against version 2018-11-09 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + }, + "x-ms-copy-id": { + "x-ms-client-name": "CopyId", + "type": "string", + "description": "String identifier for this copy operation." + }, + "x-ms-copy-status": { + "x-ms-client-name": "CopyStatus", + "description": "State of the copy operation identified by x-ms-copy-id.", + "type": "string", + "enum": [ + "success" + ], + "x-ms-enum": { + "name": "SyncCopyStatusType", + "modelAsString": false + } + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "x-ms-requires-sync", + "in": "header", + "required": true, + "type": "string", + "enum": [ + "true" + ] + } + ] + }, + "/{containerName}/{blob}?comp=copy©id={CopyId}": { + "put": { + "tags": [ + "blob" + ], + "operationId": "Blob_AbortCopyFromURL", + "description": "The Abort Copy From URL operation aborts a pending Copy From URL operation, and leaves a destination blob with zero length and full metadata.", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Blob" + }, + { + "$ref": "#/parameters/CopyId" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/LeaseIdOptional" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "204": { + "description": "The delete request was accepted and the blob will be deleted.", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "copy" + ] + }, + { + "name": "x-ms-copy-action", + "x-ms-client-name": "copyActionAbortConstant", + "in": "header", + "required": true, + "type": "string", + "enum": [ + "abort" + ], + "x-ms-parameter-location": "method" + } + ] + }, + "/{containerName}/{blob}?comp=tier": { + "put": { + "tags": [ + "blobs" + ], + "operationId": "Blob_SetTier", + "description": "The Set Tier operation sets the tier on a blob. The operation is allowed on a page blob in a premium storage account and on a block blob in a blob storage account (locally redundant storage only). A premium page blob's tier determines the allowed size, IOPS, and bandwidth of the blob. A block blob's tier determines Hot/Cool/Archive storage type. This operation does not update the blob's ETag.", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Blob" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/AccessTier" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + }, + { + "$ref": "#/parameters/LeaseIdOptional" + } + ], + "responses": { + "200": { + "description": "The new tier will take effect immediately.", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and newer." + } + } + }, + "202": { + "description": "The transition to the new tier is pending.", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and newer." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "tier" + ] + } + ] + }, + "/{containerName}/{blob}?restype=account&comp=properties": { + "get": { + "tags": [ + "blob" + ], + "operationId": "Blob_GetAccountInfo", + "description": "Returns the sku name and account kind ", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Blob" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Success (OK)", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + }, + "x-ms-sku-name": { + "x-ms-client-name": "SkuName", + "type": "string", + "enum": [ + "Standard_LRS", + "Standard_GRS", + "Standard_RAGRS", + "Standard_ZRS", + "Premium_LRS" + ], + "x-ms-enum": { + "name": "SkuName", + "modelAsString": false + }, + "description": "Identifies the sku name of the account" + }, + "x-ms-account-kind": { + "x-ms-client-name": "AccountKind", + "type": "string", + "enum": [ + "Storage", + "BlobStorage", + "StorageV2" + ], + "x-ms-enum": { + "name": "AccountKind", + "modelAsString": false + }, + "description": "Identifies the account kind" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "restype", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "account" + ] + }, + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "properties" + ] + } + ] + }, + "/{containerName}/{blob}?comp=block": { + "put": { + "tags": [ + "blockblob" + ], + "operationId": "BlockBlob_StageBlock", + "description": "The Stage Block operation creates a new block to be committed as part of a blob", + "consumes": [ + "application/octet-stream" + ], + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Blob" + }, + { + "$ref": "#/parameters/BlockId" + }, + { + "$ref": "#/parameters/ContentLength" + }, + { + "$ref": "#/parameters/ContentMD5" + }, + { + "$ref": "#/parameters/Body" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/LeaseIdOptional" + }, + { + "$ref": "#/parameters/EncryptionKey" + }, + { + "$ref": "#/parameters/EncryptionKeySha256" + }, + { + "$ref": "#/parameters/EncryptionAlgorithm" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "201": { + "description": "The block was created.", + "headers": { + "Content-MD5": { + "type": "string", + "format": "byte", + "description": "If the blob has an MD5 hash and this operation is to read the full blob, this response header is returned so that the client can check for message content integrity." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + }, + "x-ms-request-server-encrypted": { + "x-ms-client-name": "IsServerEncrypted", + "type": "boolean", + "description": "The value of this header is set to true if the contents of the request are successfully encrypted using the specified algorithm, and false otherwise." + }, + "x-ms-encryption-key-sha256": { + "x-ms-client-name": "EncryptionKeySha256", + "type": "string", + "description": "The SHA-256 hash of the encryption key used to encrypt the block. This header is only returned when the block was encrypted with a customer-provided key." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "block" + ] + } + ] + }, + "/{containerName}/{blob}?comp=block&fromURL": { + "put": { + "tags": [ + "blockblob" + ], + "operationId": "BlockBlob_StageBlockFromURL", + "description": "The Stage Block operation creates a new block to be committed as part of a blob where the contents are read from a URL.", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Blob" + }, + { + "$ref": "#/parameters/BlockId" + }, + { + "$ref": "#/parameters/ContentLength" + }, + { + "$ref": "#/parameters/SourceUrl" + }, + { + "$ref": "#/parameters/SourceRange" + }, + { + "$ref": "#/parameters/SourceContentMD5" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/LeaseIdOptional" + }, + { + "$ref": "#/parameters/EncryptionKey" + }, + { + "$ref": "#/parameters/EncryptionKeySha256" + }, + { + "$ref": "#/parameters/EncryptionAlgorithm" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + }, + { + "$ref": "#/parameters/SourceIfModifiedSince" + }, + { + "$ref": "#/parameters/SourceIfUnmodifiedSince" + }, + { + "$ref": "#/parameters/SourceIfMatch" + }, + { + "$ref": "#/parameters/SourceIfNoneMatch" + } + ], + "responses": { + "201": { + "description": "The block was created.", + "headers": { + "Content-MD5": { + "type": "string", + "format": "byte", + "description": "If the blob has an MD5 hash and this operation is to read the full blob, this response header is returned so that the client can check for message content integrity." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + }, + "x-ms-request-server-encrypted": { + "x-ms-client-name": "IsServerEncrypted", + "type": "boolean", + "description": "The value of this header is set to true if the contents of the request are successfully encrypted using the specified algorithm, and false otherwise." + }, + "x-ms-encryption-key-sha256": { + "x-ms-client-name": "EncryptionKeySha256", + "type": "string", + "description": "The SHA-256 hash of the encryption key used to encrypt the block. This header is only returned when the block was encrypted with a customer-provided key." + } + } + }, + "304": { + "description": "The condition specified using HTTP conditional header(s) is not met.", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "block" + ] + } + ] + }, + "/{containerName}/{blob}?comp=blocklist": { + "put": { + "tags": [ + "blockblob" + ], + "operationId": "BlockBlob_CommitBlockList", + "description": "The Commit Block List operation writes a blob by specifying the list of block IDs that make up the blob. In order to be written as part of a blob, a block must have been successfully written to the server in a prior Put Block operation. You can call Put Block List to update a blob by uploading only those blocks that have changed, then committing the new and existing blocks together. You can do this by specifying whether to commit a block from the committed block list or from the uncommitted block list, or to commit the most recently uploaded version of the block, whichever list it may belong to.", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Blob" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/BlobCacheControl" + }, + { + "$ref": "#/parameters/BlobContentType" + }, + { + "$ref": "#/parameters/BlobContentEncoding" + }, + { + "$ref": "#/parameters/BlobContentLanguage" + }, + { + "$ref": "#/parameters/BlobContentMD5" + }, + { + "$ref": "#/parameters/Metadata" + }, + { + "$ref": "#/parameters/LeaseIdOptional" + }, + { + "$ref": "#/parameters/BlobContentDisposition" + }, + { + "$ref": "#/parameters/EncryptionKey" + }, + { + "$ref": "#/parameters/EncryptionKeySha256" + }, + { + "$ref": "#/parameters/EncryptionAlgorithm" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/IfUnmodifiedSince" + }, + { + "$ref": "#/parameters/IfMatch" + }, + { + "$ref": "#/parameters/IfNoneMatch" + }, + { + "name": "blocks", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/BlockLookupList" + } + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "201": { + "description": "The block list was recorded.", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the container was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "Content-MD5": { + "type": "string", + "format": "byte", + "description": "If the blob has an MD5 hash and this operation is to read the full blob, this response header is returned so that the client can check for message content integrity." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "x-ms-version-id": { + "x-ms-client-name": "VersionId", + "type": "string", + "description": "UTC date/time value generated by the service that identifies a version of the blob. This header is returned for requests made against version 2018-11-09 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + }, + "x-ms-request-server-encrypted": { + "x-ms-client-name": "IsServerEncrypted", + "type": "boolean", + "description": "The value of this header is set to true if the contents of the request are successfully encrypted using the specified algorithm, and false otherwise." + }, + "x-ms-encryption-key-sha256": { + "x-ms-client-name": "EncryptionKeySha256", + "type": "string", + "description": "The SHA-256 hash of the encryption key used to encrypt the blob. This header is only returned when the blob was encrypted with a customer-provided key." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "get": { + "tags": [ + "blockblob" + ], + "operationId": "BlockBlob_GetBlockList", + "description": "The Get Block List operation retrieves the list of blocks that have been uploaded as part of a block blob", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Blob" + }, + { + "$ref": "#/parameters/Snapshot" + }, + { + "$ref": "#/parameters/VersionId" + }, + { + "$ref": "#/parameters/BlockListType" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/LeaseIdOptional" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "The page range was written.", + "headers": { + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the container was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Content-Type": { + "type": "string", + "description": "The media type of the body of the response. For Get Block List this is 'application/xml'" + }, + "x-ms-blob-content-length": { + "x-ms-client-name": "BlobContentLength", + "type": "integer", + "format": "int64", + "description": "The size of the blob in bytes." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + }, + "schema": { + "$ref": "#/definitions/BlockList" + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "blocklist" + ] + } + ] + }, + "/{containerName}/{blob}?comp=page&update": { + "put": { + "tags": [ + "pageblob" + ], + "operationId": "PageBlob_UploadPages", + "description": "The Upload Pages operation writes a range of pages to a page blob", + "consumes": [ + "application/octet-stream" + ], + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Blob" + }, + { + "$ref": "#/parameters/Body" + }, + { + "$ref": "#/parameters/ContentLength" + }, + { + "$ref": "#/parameters/ContentMD5" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/Range" + }, + { + "$ref": "#/parameters/LeaseIdOptional" + }, + { + "$ref": "#/parameters/EncryptionKey" + }, + { + "$ref": "#/parameters/EncryptionKeySha256" + }, + { + "$ref": "#/parameters/EncryptionAlgorithm" + }, + { + "$ref": "#/parameters/IfSequenceNumberLessThanOrEqualTo" + }, + { + "$ref": "#/parameters/IfSequenceNumberLessThan" + }, + { + "$ref": "#/parameters/IfSequenceNumberEqualTo" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/IfUnmodifiedSince" + }, + { + "$ref": "#/parameters/IfMatch" + }, + { + "$ref": "#/parameters/IfNoneMatch" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "201": { + "description": "The page range was written.", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the container was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "Content-MD5": { + "type": "string", + "format": "byte", + "description": "If the blob has an MD5 hash and this operation is to read the full blob, this response header is returned so that the client can check for message content integrity." + }, + "x-ms-blob-sequence-number": { + "x-ms-client-name": "BlobSequenceNumber", + "type": "integer", + "format": "int64", + "description": "The current sequence number for the page blob." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + }, + "x-ms-request-server-encrypted": { + "x-ms-client-name": "IsServerEncrypted", + "type": "boolean", + "description": "The value of this header is set to true if the contents of the request are successfully encrypted using the specified algorithm, and false otherwise." + }, + "x-ms-encryption-key-sha256": { + "x-ms-client-name": "EncryptionKeySha256", + "type": "string", + "description": "The SHA-256 hash of the encryption key used to encrypt the pages. This header is only returned when the pages were encrypted with a customer-provided key." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "page" + ] + }, + { + "name": "x-ms-page-write", + "x-ms-client-name": "pageWrite", + "in": "header", + "required": true, + "x-ms-parameter-location": "method", + "description": "Required. You may specify one of the following options:\n - 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.\n - 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 the Range header to a value that indicates the range to clear, up to maximum blob size.", + "type": "string", + "enum": [ + "update" + ], + "x-ms-enum": { + "name": "PageWriteType", + "modelAsString": false + } + } + ] + }, + "/{containerName}/{blob}?comp=page&clear": { + "put": { + "tags": [ + "pageblob" + ], + "operationId": "PageBlob_ClearPages", + "description": "The Clear Pages operation clears a set of pages from a page blob", + "consumes": [ + "application/octet-stream" + ], + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Blob" + }, + { + "$ref": "#/parameters/ContentLength" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/Range" + }, + { + "$ref": "#/parameters/LeaseIdOptional" + }, + { + "$ref": "#/parameters/IfSequenceNumberLessThanOrEqualTo" + }, + { + "$ref": "#/parameters/IfSequenceNumberLessThan" + }, + { + "$ref": "#/parameters/IfSequenceNumberEqualTo" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/IfUnmodifiedSince" + }, + { + "$ref": "#/parameters/IfMatch" + }, + { + "$ref": "#/parameters/IfNoneMatch" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "201": { + "description": "The page range was cleared.", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the container was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "Content-MD5": { + "type": "string", + "format": "byte", + "description": "If the blob has an MD5 hash and this operation is to read the full blob, this response header is returned so that the client can check for message content integrity." + }, + "x-ms-blob-sequence-number": { + "x-ms-client-name": "BlobSequenceNumber", + "type": "integer", + "format": "int64", + "description": "The current sequence number for the page blob." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "page" + ] + }, + { + "name": "x-ms-page-write", + "x-ms-client-name": "pageWrite", + "in": "header", + "required": true, + "x-ms-parameter-location": "method", + "description": "Required. You may specify one of the following options:\n - 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.\n - 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 the Range header to a value that indicates the range to clear, up to maximum blob size.", + "type": "string", + "enum": [ + "clear" + ], + "x-ms-enum": { + "name": "PageWriteType", + "modelAsString": false + } + } + ] + }, + "/{containerName}/{blob}?comp=page&update&fromUrl": { + "put": { + "tags": [ + "pageblob" + ], + "operationId": "PageBlob_UploadPagesFromURL", + "description": "The Upload Pages operation writes a range of pages to a page blob where the contents are read from a URL", + "consumes": [ + "application/octet-stream" + ], + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Blob" + }, + { + "$ref": "#/parameters/SourceUrl" + }, + { + "$ref": "#/parameters/SourceRangeRequiredPutPageFromUrl" + }, + { + "$ref": "#/parameters/SourceContentMD5" + }, + { + "$ref": "#/parameters/ContentLength" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/RangeRequiredPutPageFromUrl" + }, + { + "$ref": "#/parameters/LeaseIdOptional" + }, + { + "$ref": "#/parameters/IfSequenceNumberLessThanOrEqualTo" + }, + { + "$ref": "#/parameters/IfSequenceNumberLessThan" + }, + { + "$ref": "#/parameters/IfSequenceNumberEqualTo" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/IfUnmodifiedSince" + }, + { + "$ref": "#/parameters/IfMatch" + }, + { + "$ref": "#/parameters/IfNoneMatch" + }, + { + "$ref": "#/parameters/SourceIfModifiedSince" + }, + { + "$ref": "#/parameters/SourceIfUnmodifiedSince" + }, + { + "$ref": "#/parameters/SourceIfMatch" + }, + { + "$ref": "#/parameters/SourceIfNoneMatch" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "201": { + "description": "The page range was written.", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the container was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "Content-MD5": { + "type": "string", + "format": "byte", + "description": "If the blob has an MD5 hash and this operation is to read the full blob, this response header is returned so that the client can check for message content integrity." + }, + "x-ms-blob-sequence-number": { + "x-ms-client-name": "BlobSequenceNumber", + "type": "integer", + "format": "int64", + "description": "The current sequence number for the page blob." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + }, + "x-ms-request-server-encrypted": { + "x-ms-client-name": "IsServerEncrypted", + "type": "boolean", + "description": "The value of this header is set to true if the contents of the request are successfully encrypted using the specified algorithm, and false otherwise." + } + } + }, + "304": { + "description": "The condition specified using HTTP conditional header(s) is not met.", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "page" + ] + }, + { + "name": "x-ms-page-write", + "x-ms-client-name": "pageWrite", + "in": "header", + "required": true, + "x-ms-parameter-location": "method", + "description": "Required. You may specify one of the following options:\n - 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.\n - 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 the Range header to a value that indicates the range to clear, up to maximum blob size.", + "type": "string", + "enum": [ + "update" + ], + "x-ms-enum": { + "name": "PageWriteType", + "modelAsString": false + } + } + ] + }, + "/{containerName}/{blob}?comp=pagelist": { + "get": { + "tags": [ + "pageblob" + ], + "operationId": "PageBlob_GetPageRanges", + "description": "The Get Page Ranges operation returns the list of valid page ranges for a page blob, version or snapshot of a page blob", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Blob" + }, + { + "$ref": "#/parameters/Snapshot" + }, + { + "$ref": "#/parameters/VersionId" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/Range" + }, + { + "$ref": "#/parameters/LeaseIdOptional" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/IfUnmodifiedSince" + }, + { + "$ref": "#/parameters/IfMatch" + }, + { + "$ref": "#/parameters/IfNoneMatch" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "Information on the page blob was found.", + "headers": { + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the container was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "x-ms-blob-content-length": { + "x-ms-client-name": "BlobContentLength", + "type": "integer", + "format": "int64", + "description": "The size of the blob in bytes." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + }, + "schema": { + "$ref": "#/definitions/PageList" + } + }, + "304": { + "description": "The condition specified using HTTP conditional header(s) is not met.", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "pagelist" + ] + } + ] + }, + "/{containerName}/{blob}?comp=pagelist&diff": { + "get": { + "tags": [ + "pageblob" + ], + "operationId": "PageBlob_GetPageRangesDiff", + "description": "[Update] The Get Page Ranges Diff operation returns the list of valid page ranges for a page blob that were changed between target blob and previous snapshot or version.", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Blob" + }, + { + "$ref": "#/parameters/Snapshot" + }, + { + "$ref": "#/parameters/VersionId" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/PrevSnapshot" + }, + { + "$ref": "#/parameters/Range" + }, + { + "$ref": "#/parameters/LeaseIdOptional" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/IfUnmodifiedSince" + }, + { + "$ref": "#/parameters/IfMatch" + }, + { + "$ref": "#/parameters/IfNoneMatch" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "Information on the page blob was found.", + "headers": { + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the container was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "x-ms-blob-content-length": { + "x-ms-client-name": "BlobContentLength", + "type": "integer", + "format": "int64", + "description": "The size of the blob in bytes." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + }, + "schema": { + "$ref": "#/definitions/PageList" + } + }, + "304": { + "description": "The condition specified using HTTP conditional header(s) is not met.", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "pagelist" + ] + } + ] + }, + "/{containerName}/{blob}?comp=properties&Resize": { + "put": { + "tags": [ + "pageblob" + ], + "operationId": "PageBlob_Resize", + "description": "Resize the Blob", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Blob" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/LeaseIdOptional" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/IfUnmodifiedSince" + }, + { + "$ref": "#/parameters/IfMatch" + }, + { + "$ref": "#/parameters/IfNoneMatch" + }, + { + "$ref": "#/parameters/BlobContentLengthRequired" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "The Blob was resized successfully", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the container was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "x-ms-blob-sequence-number": { + "x-ms-client-name": "BlobSequenceNumber", + "type": "integer", + "format": "int64", + "description": "The current sequence number for a page blob. This header is not returned for block blobs or append blobs" + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "properties" + ] + } + ] + }, + "/{containerName}/{blob}?comp=properties&UpdateSequenceNumber": { + "put": { + "tags": [ + "pageblob" + ], + "operationId": "PageBlob_UpdateSequenceNumber", + "description": "Update the sequence number of the blob", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Blob" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/LeaseIdOptional" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/IfUnmodifiedSince" + }, + { + "$ref": "#/parameters/IfMatch" + }, + { + "$ref": "#/parameters/IfNoneMatch" + }, + { + "$ref": "#/parameters/SequenceNumberAction" + }, + { + "$ref": "#/parameters/BlobSequenceNumber" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "The sequence numbers were updated successfully.", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the container was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "x-ms-blob-sequence-number": { + "x-ms-client-name": "BlobSequenceNumber", + "type": "integer", + "format": "int64", + "description": "The current sequence number for a page blob. This header is not returned for block blobs or append blobs" + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "properties" + ] + } + ] + }, + "/{containerName}/{blob}?comp=incrementalcopy": { + "put": { + "tags": [ + "pageblob" + ], + "operationId": "PageBlob_CopyIncremental", + "description": "The Copy Incremental operation copies a snapshot of the source page blob to a destination page blob. The snapshot is copied such that only the differential changes between the previously copied snapshot are transferred to the destination. The copied snapshots are complete copies of the original snapshot and can be read or copied from as usual. This API is supported since REST version 2016-05-31.", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Blob" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/IfUnmodifiedSince" + }, + { + "$ref": "#/parameters/IfMatch" + }, + { + "$ref": "#/parameters/IfNoneMatch" + }, + { + "$ref": "#/parameters/CopySource" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "202": { + "description": "The blob was copied.", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the container was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + }, + "x-ms-copy-id": { + "x-ms-client-name": "CopyId", + "type": "string", + "description": "String identifier for this copy operation. Use with Get Blob Properties to check the status of this copy operation, or pass to Abort Copy Blob to abort a pending copy." + }, + "x-ms-copy-status": { + "x-ms-client-name": "CopyStatus", + "description": "State of the copy operation identified by x-ms-copy-id.", + "type": "string", + "enum": [ + "pending", + "success", + "aborted", + "failed" + ], + "x-ms-enum": { + "name": "CopyStatusType", + "modelAsString": false + } + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "incrementalcopy" + ] + } + ] + }, + "/{containerName}/{blob}?comp=appendblock": { + "put": { + "tags": [ + "appendblob" + ], + "consumes": [ + "application/octet-stream" + ], + "operationId": "AppendBlob_AppendBlock", + "description": "The Append Block operation commits a new block of data to the end of an existing append blob. The Append Block operation is permitted only if the blob was created with x-ms-blob-type set to AppendBlob. Append Block is supported only on version 2015-02-21 version or later.", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Blob" + }, + { + "$ref": "#/parameters/Body" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ContentLength" + }, + { + "$ref": "#/parameters/ContentMD5" + }, + { + "$ref": "#/parameters/LeaseIdOptional" + }, + { + "$ref": "#/parameters/BlobConditionMaxSize" + }, + { + "$ref": "#/parameters/BlobConditionAppendPos" + }, + { + "$ref": "#/parameters/EncryptionKey" + }, + { + "$ref": "#/parameters/EncryptionKeySha256" + }, + { + "$ref": "#/parameters/EncryptionAlgorithm" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/IfUnmodifiedSince" + }, + { + "$ref": "#/parameters/IfMatch" + }, + { + "$ref": "#/parameters/IfNoneMatch" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "201": { + "description": "The block was created.", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the container was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "Content-MD5": { + "type": "string", + "format": "byte", + "description": "If the blob has an MD5 hash and this operation is to read the full blob, this response header is returned so that the client can check for message content integrity." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + }, + "x-ms-blob-append-offset": { + "x-ms-client-name": "BlobAppendOffset", + "type": "string", + "description": "This response header is returned only for append operations. It returns the offset at which the block was committed, in bytes." + }, + "x-ms-blob-committed-block-count": { + "x-ms-client-name": "BlobCommittedBlockCount", + "type": "integer", + "description": "The number of committed blocks present in the blob. This header is returned only for append blobs." + }, + "x-ms-request-server-encrypted": { + "x-ms-client-name": "IsServerEncrypted", + "type": "boolean", + "description": "The value of this header is set to true if the contents of the request are successfully encrypted using the specified algorithm, and false otherwise." + }, + "x-ms-encryption-key-sha256": { + "x-ms-client-name": "EncryptionKeySha256", + "type": "string", + "description": "The SHA-256 hash of the encryption key used to encrypt the block. This header is only returned when the block was encrypted with a customer-provided key." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "appendblock" + ] + } + ] + }, + "/{containerName}/{blob}?comp=appendblock&fromUrl": { + "put": { + "tags": [ + "appendblob" + ], + "operationId": "AppendBlob_AppendBlockFromUrl", + "description": "The Append Block operation commits a new block of data to the end of an existing append blob where the contents are read from a source url. The Append Block operation is permitted only if the blob was created with x-ms-blob-type set to AppendBlob. Append Block is supported only on version 2015-02-21 version or later.", + "parameters": [ + { + "$ref": "#/parameters/ContainerName" + }, + { + "$ref": "#/parameters/Blob" + }, + { + "$ref": "#/parameters/SourceUrl" + }, + { + "$ref": "#/parameters/SourceRange" + }, + { + "$ref": "#/parameters/SourceContentMD5" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ContentLength" + }, + { + "$ref": "#/parameters/LeaseIdOptional" + }, + { + "$ref": "#/parameters/BlobConditionMaxSize" + }, + { + "$ref": "#/parameters/BlobConditionAppendPos" + }, + { + "$ref": "#/parameters/IfModifiedSince" + }, + { + "$ref": "#/parameters/IfUnmodifiedSince" + }, + { + "$ref": "#/parameters/IfMatch" + }, + { + "$ref": "#/parameters/IfNoneMatch" + }, + { + "$ref": "#/parameters/SourceIfModifiedSince" + }, + { + "$ref": "#/parameters/SourceIfUnmodifiedSince" + }, + { + "$ref": "#/parameters/SourceIfMatch" + }, + { + "$ref": "#/parameters/SourceIfNoneMatch" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "201": { + "description": "The block was created.", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the container was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob." + }, + "Content-MD5": { + "type": "string", + "format": "byte", + "description": "If the blob has an MD5 hash and this operation is to read the full blob, this response header is returned so that the client can check for message content integrity." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + }, + "x-ms-blob-append-offset": { + "x-ms-client-name": "BlobAppendOffset", + "type": "string", + "description": "This response header is returned only for append operations. It returns the offset at which the block was committed, in bytes." + }, + "x-ms-blob-committed-block-count": { + "x-ms-client-name": "BlobCommittedBlockCount", + "type": "integer", + "description": "The number of committed blocks present in the blob. This header is returned only for append blobs." + } + } + }, + "304": { + "description": "The condition specified using HTTP conditional header(s) is not met.", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "appendblock" + ] + } + ] + } + }, + "definitions": { + "KeyInfo": { + "type": "object", + "required": [ + "Start", + "Expiry" + ], + "description": "Key information", + "properties": { + "Start": { + "description": "The date-time the key is active in ISO 8601 UTC time", + "type": "string" + }, + "Expiry": { + "description": "The date-time the key expires in ISO 8601 UTC time", + "type": "string" + } + } + }, + "UserDelegationKey": { + "type": "object", + "required": [ + "SignedOid", + "SignedTid", + "SignedStart", + "SignedExpiry", + "SignedService", + "SignedVersion", + "Value" + ], + "description": "A user delegation key", + "properties": { + "SignedOid": { + "description": "The Azure Active Directory object ID in GUID format.", + "type": "string" + }, + "SignedTid": { + "description": "The Azure Active Directory tenant ID in GUID format", + "type": "string" + }, + "SignedStart": { + "description": "The date-time the key is active", + "type": "string", + "format": "date-time" + }, + "SignedExpiry": { + "description": "The date-time the key expires", + "type": "string", + "format": "date-time" + }, + "SignedService": { + "description": "Abbreviation of the Azure Storage service that accepts the key", + "type": "string" + }, + "SignedVersion": { + "description": "The service version that created the key", + "type": "string" + }, + "Value": { + "description": "The key as a base64 string", + "type": "string" + } + } + }, + "PublicAccessType": { + "type": "string", + "enum": [ + "container", + "blob" + ], + "x-ms-enum": { + "name": "PublicAccessType", + "modelAsString": true + } + }, + "CopyStatus": { + "type": "string", + "enum": [ + "pending", + "success", + "aborted", + "failed" + ], + "x-ms-enum": { + "name": "CopyStatusType", + "modelAsString": false + } + }, + "LeaseDuration": { + "type": "string", + "enum": [ + "infinite", + "fixed" + ], + "x-ms-enum": { + "name": "LeaseDurationType", + "modelAsString": false + } + }, + "LeaseState": { + "type": "string", + "enum": [ + "available", + "leased", + "expired", + "breaking", + "broken" + ], + "x-ms-enum": { + "name": "LeaseStateType", + "modelAsString": false + } + }, + "LeaseStatus": { + "type": "string", + "enum": [ + "locked", + "unlocked" + ], + "x-ms-enum": { + "name": "LeaseStatusType", + "modelAsString": false + } + }, + "StorageError": { + "type": "object", + "properties": { + "Code": { + "type": "string" + }, + "Message": { + "type": "string" + } + } + }, + "AccessPolicy": { + "type": "object", + "required": [ + "Start", + "Expiry", + "Permission" + ], + "description": "An Access policy", + "properties": { + "Start": { + "description": "the date-time the policy is active", + "type": "string", + "format": "date-time" + }, + "Expiry": { + "description": "the date-time the policy expires", + "type": "string", + "format": "date-time" + }, + "Permission": { + "description": "the permissions for the acl policy", + "type": "string" + } + } + }, + "AccessTier": { + "type": "string", + "enum": [ + "P4", + "P6", + "P10", + "P20", + "P30", + "P40", + "P50", + "Hot", + "Cool", + "Archive" + ], + "x-ms-enum": { + "name": "AccessTier", + "modelAsString": true + } + }, + "ArchiveStatus": { + "type": "string", + "enum": [ + "rehydrate-pending-to-hot", + "rehydrate-pending-to-cool" + ], + "x-ms-enum": { + "name": "ArchiveStatus", + "modelAsString": true + } + }, + "BlobItem": { + "xml": { + "name": "Blob" + }, + "description": "An Azure Storage blob", + "type": "object", + "required": [ + "Name", + "Deleted", + "Snapshot", + "VersionId", + "Properties" + ], + "properties": { + "Name": { + "type": "string" + }, + "Deleted": { + "type": "boolean" + }, + "Snapshot": { + "type": "string" + }, + "VersionId": { + "type": "string" + }, + "Properties": { + "$ref": "#/definitions/BlobProperties" + }, + "Metadata": { + "$ref": "#/definitions/BlobMetadata" + } + } + }, + "BlobProperties": { + "xml": { + "name": "Properties" + }, + "description": "Properties of a blob", + "type": "object", + "required": [ + "Etag", + "Last-Modified" + ], + "properties": { + "Creation-Time": { + "type": "string", + "format": "date-time-rfc1123" + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123" + }, + "Etag": { + "type": "string", + "format": "etag" + }, + "Content-Length": { + "type": "integer", + "format": "int64", + "description": "Size in bytes" + }, + "Content-Type": { + "type": "string" + }, + "Content-Encoding": { + "type": "string" + }, + "Content-Language": { + "type": "string" + }, + "Content-MD5": { + "type": "string", + "format": "byte" + }, + "Content-Disposition": { + "type": "string" + }, + "Cache-Control": { + "type": "string" + }, + "x-ms-blob-sequence-number": { + "x-ms-client-name": "blobSequenceNumber", + "type": "integer", + "format": "int64" + }, + "BlobType": { + "type": "string", + "enum": [ + "BlockBlob", + "PageBlob", + "AppendBlob" + ], + "x-ms-enum": { + "name": "BlobType", + "modelAsString": false + } + }, + "LeaseStatus": { + "$ref": "#/definitions/LeaseStatus" + }, + "LeaseState": { + "$ref": "#/definitions/LeaseState" + }, + "LeaseDuration": { + "$ref": "#/definitions/LeaseDuration" + }, + "CopyId": { + "type": "string" + }, + "CopyStatus": { + "$ref": "#/definitions/CopyStatus" + }, + "CopySource": { + "type": "string" + }, + "CopyProgress": { + "type": "string" + }, + "CopyCompletionTime": { + "type": "string", + "format": "date-time-rfc1123" + }, + "CopyStatusDescription": { + "type": "string" + }, + "ServerEncrypted": { + "type": "boolean" + }, + "IncrementalCopy": { + "type": "boolean" + }, + "DestinationSnapshot": { + "type": "string" + }, + "DeletedTime": { + "type": "string", + "format": "date-time-rfc1123" + }, + "RemainingRetentionDays": { + "type": "integer" + }, + "AccessTier": { + "$ref": "#/definitions/AccessTier" + }, + "AccessTierInferred": { + "type": "boolean" + }, + "ArchiveStatus": { + "$ref": "#/definitions/ArchiveStatus" + }, + "CustomerProvidedKeySha256": { + "type": "string" + }, + "AccessTierChangeTime": { + "type": "string", + "format": "date-time-rfc1123" + } + } + }, + "ListBlobsFlatSegmentResponse": { + "xml": { + "name": "EnumerationResults" + }, + "description": "An enumeration of blobs", + "type": "object", + "required": [ + "ServiceEndpoint", + "ContainerName", + "Prefix", + "Marker", + "MaxResults", + "Delimiter", + "Segment", + "NextMarker" + ], + "properties": { + "ServiceEndpoint": { + "type": "string", + "xml": { + "attribute": true + } + }, + "ContainerName": { + "type": "string", + "xml": { + "attribute": true + } + }, + "Prefix": { + "type": "string" + }, + "Marker": { + "type": "string" + }, + "MaxResults": { + "type": "integer" + }, + "Delimiter": { + "type": "string" + }, + "Segment": { + "$ref": "#/definitions/BlobFlatListSegment" + }, + "NextMarker": { + "type": "string" + } + } + }, + "ListBlobsHierarchySegmentResponse": { + "xml": { + "name": "EnumerationResults" + }, + "description": "An enumeration of blobs", + "type": "object", + "required": [ + "ServiceEndpoint", + "ContainerName", + "Prefix", + "Marker", + "MaxResults", + "Delimiter", + "Segment", + "NextMarker" + ], + "properties": { + "ServiceEndpoint": { + "type": "string", + "xml": { + "attribute": true + } + }, + "ContainerName": { + "type": "string", + "xml": { + "attribute": true + } + }, + "Prefix": { + "type": "string" + }, + "Marker": { + "type": "string" + }, + "MaxResults": { + "type": "integer" + }, + "Delimiter": { + "type": "string" + }, + "Segment": { + "$ref": "#/definitions/BlobHierarchyListSegment" + }, + "NextMarker": { + "type": "string" + } + } + }, + "BlobFlatListSegment": { + "xml": { + "name": "Blobs" + }, + "required": [ + "BlobItems" + ], + "type": "object", + "properties": { + "BlobItems": { + "type": "array", + "items": { + "$ref": "#/definitions/BlobItem" + } + } + } + }, + "BlobHierarchyListSegment": { + "xml": { + "name": "Blobs" + }, + "type": "object", + "required": [ + "BlobItems" + ], + "properties": { + "BlobPrefixes": { + "type": "array", + "items": { + "$ref": "#/definitions/BlobPrefix" + } + }, + "BlobItems": { + "type": "array", + "items": { + "$ref": "#/definitions/BlobItem" + } + } + } + }, + "BlobPrefix": { + "type": "object", + "required": [ + "Name" + ], + "properties": { + "Name": { + "type": "string" + } + } + }, + "Block": { + "type": "object", + "required": [ + "Name", + "Size" + ], + "description": "Represents a single block in a block blob. It describes the block's ID and size.", + "properties": { + "Name": { + "description": "The base64 encoded block ID.", + "type": "string" + }, + "Size": { + "description": "The block size in bytes.", + "type": "integer" + } + } + }, + "BlockList": { + "type": "object", + "properties": { + "CommittedBlocks": { + "xml": { + "wrapped": true + }, + "type": "array", + "items": { + "$ref": "#/definitions/Block" + } + }, + "UncommittedBlocks": { + "xml": { + "wrapped": true + }, + "type": "array", + "items": { + "$ref": "#/definitions/Block" + } + } + } + }, + "BlockLookupList": { + "type": "object", + "properties": { + "Committed": { + "type": "array", + "items": { + "type": "string", + "xml": { + "name": "Committed" + } + } + }, + "Uncommitted": { + "type": "array", + "items": { + "type": "string", + "xml": { + "name": "Uncommitted" + } + } + }, + "Latest": { + "type": "array", + "items": { + "type": "string", + "xml": { + "name": "Latest" + } + } + } + }, + "xml": { + "name": "BlockList" + } + }, + "ContainerItem": { + "xml": { + "name": "Container" + }, + "type": "object", + "required": [ + "Name", + "Properties" + ], + "description": "An Azure Storage container", + "properties": { + "Name": { + "type": "string" + }, + "Properties": { + "$ref": "#/definitions/ContainerProperties" + }, + "Metadata": { + "$ref": "#/definitions/ContainerMetadata" + } + } + }, + "ContainerProperties": { + "type": "object", + "required": [ + "Last-Modified", + "Etag" + ], + "description": "Properties of a container", + "properties": { + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123" + }, + "Etag": { + "type": "string", + "format": "etag" + }, + "LeaseStatus": { + "$ref": "#/definitions/LeaseStatus" + }, + "LeaseState": { + "$ref": "#/definitions/LeaseState" + }, + "LeaseDuration": { + "$ref": "#/definitions/LeaseDuration" + }, + "PublicAccess": { + "$ref": "#/definitions/PublicAccessType" + }, + "HasImmutabilityPolicy": { + "type": "boolean" + }, + "HasLegalHold": { + "type": "boolean" + } + } + }, + "ListContainersSegmentResponse": { + "xml": { + "name": "EnumerationResults" + }, + "description": "An enumeration of containers", + "type": "object", + "required": [ + "ServiceEndpoint", + "Prefix", + "MaxResults", + "NextMarker", + "ContainerItems" + ], + "properties": { + "ServiceEndpoint": { + "type": "string", + "xml": { + "attribute": true + } + }, + "Prefix": { + "type": "string" + }, + "Marker": { + "type": "string" + }, + "MaxResults": { + "type": "integer" + }, + "ContainerItems": { + "xml": { + "wrapped": true, + "name": "Containers" + }, + "type": "array", + "items": { + "$ref": "#/definitions/ContainerItem" + } + }, + "NextMarker": { + "type": "string" + } + } + }, + "CorsRule": { + "description": "CORS is an HTTP feature that enables a web application running under one domain to access resources in another domain. Web browsers implement a security restriction known as same-origin policy that prevents a web page from calling APIs in a different domain; CORS provides a secure way to allow one domain (the origin domain) to call APIs in another domain", + "type": "object", + "required": [ + "AllowedOrigins", + "AllowedMethods", + "AllowedHeaders", + "ExposedHeaders", + "MaxAgeInSeconds" + ], + "properties": { + "AllowedOrigins": { + "description": "The origin domains that are permitted to make a request against the storage service via CORS. The origin domain is the domain from which the request originates. Note that the origin must be an exact case-sensitive match with the origin that the user age sends to the service. You can also use the wildcard character '*' to allow all origin domains to make requests via CORS.", + "type": "string" + }, + "AllowedMethods": { + "description": "The methods (HTTP request verbs) that the origin domain may use for a CORS request. (comma separated)", + "type": "string" + }, + "AllowedHeaders": { + "description": "the request headers that the origin domain may specify on the CORS request.", + "type": "string" + }, + "ExposedHeaders": { + "description": "The response headers that may be sent in the response to the CORS request and exposed by the browser to the request issuer", + "type": "string" + }, + "MaxAgeInSeconds": { + "description": "The maximum amount time that a browser should cache the preflight OPTIONS request.", + "type": "integer", + "minimum": 0 + } + } + }, + "ErrorCode": { + "description": "Error codes returned by the service", + "type": "string", + "enum": [ + "AccountAlreadyExists", + "AccountBeingCreated", + "AccountIsDisabled", + "AuthenticationFailed", + "AuthorizationFailure", + "ConditionHeadersNotSupported", + "ConditionNotMet", + "EmptyMetadataKey", + "InsufficientAccountPermissions", + "InternalError", + "InvalidAuthenticationInfo", + "InvalidHeaderValue", + "InvalidHttpVerb", + "InvalidInput", + "InvalidMd5", + "InvalidMetadata", + "InvalidQueryParameterValue", + "InvalidRange", + "InvalidResourceName", + "InvalidUri", + "InvalidXmlDocument", + "InvalidXmlNodeValue", + "Md5Mismatch", + "MetadataTooLarge", + "MissingContentLengthHeader", + "MissingRequiredQueryParameter", + "MissingRequiredHeader", + "MissingRequiredXmlNode", + "MultipleConditionHeadersNotSupported", + "OperationTimedOut", + "OutOfRangeInput", + "OutOfRangeQueryParameterValue", + "RequestBodyTooLarge", + "ResourceTypeMismatch", + "RequestUrlFailedToParse", + "ResourceAlreadyExists", + "ResourceNotFound", + "ServerBusy", + "UnsupportedHeader", + "UnsupportedXmlNode", + "UnsupportedQueryParameter", + "UnsupportedHttpVerb", + "AppendPositionConditionNotMet", + "BlobAlreadyExists", + "BlobNotFound", + "BlobOverwritten", + "BlobTierInadequateForContentLength", + "BlockCountExceedsLimit", + "BlockListTooLong", + "CannotChangeToLowerTier", + "CannotVerifyCopySource", + "ContainerAlreadyExists", + "ContainerBeingDeleted", + "ContainerDisabled", + "ContainerNotFound", + "ContentLengthLargerThanTierLimit", + "CopyAcrossAccountsNotSupported", + "CopyIdMismatch", + "FeatureVersionMismatch", + "IncrementalCopyBlobMismatch", + "IncrementalCopyOfEralierVersionSnapshotNotAllowed", + "IncrementalCopySourceMustBeSnapshot", + "InfiniteLeaseDurationRequired", + "InvalidBlobOrBlock", + "InvalidBlobTier", + "InvalidBlobType", + "InvalidBlockId", + "InvalidBlockList", + "InvalidOperation", + "InvalidPageRange", + "InvalidSourceBlobType", + "InvalidSourceBlobUrl", + "InvalidVersionForPageBlobOperation", + "LeaseAlreadyPresent", + "LeaseAlreadyBroken", + "LeaseIdMismatchWithBlobOperation", + "LeaseIdMismatchWithContainerOperation", + "LeaseIdMismatchWithLeaseOperation", + "LeaseIdMissing", + "LeaseIsBreakingAndCannotBeAcquired", + "LeaseIsBreakingAndCannotBeChanged", + "LeaseIsBrokenAndCannotBeRenewed", + "LeaseLost", + "LeaseNotPresentWithBlobOperation", + "LeaseNotPresentWithContainerOperation", + "LeaseNotPresentWithLeaseOperation", + "MaxBlobSizeConditionNotMet", + "NoPendingCopyOperation", + "OperationNotAllowedOnIncrementalCopyBlob", + "PendingCopyOperation", + "PreviousSnapshotCannotBeNewer", + "PreviousSnapshotNotFound", + "PreviousSnapshotOperationNotSupported", + "SequenceNumberConditionNotMet", + "SequenceNumberIncrementTooLarge", + "SnapshotCountExceeded", + "SnaphotOperationRateExceeded", + "SnapshotsPresent", + "SourceConditionNotMet", + "SystemInUse", + "TargetConditionNotMet", + "UnauthorizedBlobOverwrite", + "BlobBeingRehydrated", + "BlobArchived", + "BlobNotArchived" + ], + "x-ms-enum": { + "name": "StorageErrorCode", + "modelAsString": true + } + }, + "GeoReplication": { + "description": "Geo-Replication information for the Secondary Storage Service", + "type": "object", + "required": [ + "Status", + "LastSyncTime" + ], + "properties": { + "Status": { + "description": "The status of the secondary location", + "type": "string", + "enum": [ + "live", + "bootstrap", + "unavailable" + ], + "x-ms-enum": { + "name": "GeoReplicationStatusType", + "modelAsString": true + } + }, + "LastSyncTime": { + "description": "A GMT date/time value, to the second. All primary writes preceding this value are guaranteed to be available for read operations at the secondary. Primary writes after this point in time may or may not be available for reads.", + "type": "string", + "format": "date-time-rfc1123" + } + } + }, + "Logging": { + "description": "Azure Analytics Logging settings.", + "type": "object", + "required": [ + "Version", + "Delete", + "Read", + "Write", + "RetentionPolicy" + ], + "properties": { + "Version": { + "description": "The version of Storage Analytics to configure.", + "type": "string" + }, + "Delete": { + "description": "Indicates whether all delete requests should be logged.", + "type": "boolean" + }, + "Read": { + "description": "Indicates whether all read requests should be logged.", + "type": "boolean" + }, + "Write": { + "description": "Indicates whether all write requests should be logged.", + "type": "boolean" + }, + "RetentionPolicy": { + "$ref": "#/definitions/RetentionPolicy" + } + } + }, + "ContainerMetadata": { + "type": "object", + "xml": { + "name": "Metadata" + }, + "additionalProperties": { + "type": "string" + } + }, + "BlobMetadata": { + "type": "object", + "xml": { + "name": "Metadata" + }, + "properties": { + "Encrypted": { + "type": "string", + "xml": { + "attribute": true + } + } + }, + "additionalProperties": { + "type": "string" + } + }, + "Metrics": { + "description": "a summary of request statistics grouped by API in hour or minute aggregates for blobs", + "required": [ + "Enabled" + ], + "properties": { + "Version": { + "description": "The version of Storage Analytics to configure.", + "type": "string" + }, + "Enabled": { + "description": "Indicates whether metrics are enabled for the Blob service.", + "type": "boolean" + }, + "IncludeAPIs": { + "description": "Indicates whether metrics should generate summary statistics for called API operations.", + "type": "boolean" + }, + "RetentionPolicy": { + "$ref": "#/definitions/RetentionPolicy" + } + } + }, + "PageList": { + "description": "the list of pages", + "type": "object", + "properties": { + "PageRange": { + "type": "array", + "items": { + "$ref": "#/definitions/PageRange" + } + }, + "ClearRange": { + "type": "array", + "items": { + "$ref": "#/definitions/ClearRange" + } + } + } + }, + "PageRange": { + "type": "object", + "required": [ + "Start", + "End" + ], + "properties": { + "Start": { + "type": "integer", + "format": "int64", + "xml": { + "name": "Start" + } + }, + "End": { + "type": "integer", + "format": "int64", + "xml": { + "name": "End" + } + } + }, + "xml": { + "name": "PageRange" + } + }, + "ClearRange": { + "type": "object", + "required": [ + "Start", + "End" + ], + "properties": { + "Start": { + "type": "integer", + "format": "int64", + "xml": { + "name": "Start" + } + }, + "End": { + "type": "integer", + "format": "int64", + "xml": { + "name": "End" + } + } + }, + "xml": { + "name": "ClearRange" + } + }, + "RetentionPolicy": { + "description": "the retention policy which determines how long the associated data should persist", + "type": "object", + "required": [ + "Enabled" + ], + "properties": { + "Enabled": { + "description": "Indicates whether a retention policy is enabled for the storage service", + "type": "boolean" + }, + "Days": { + "description": "Indicates the number of days that metrics or logging or soft-deleted data should be retained. All data older than this value will be deleted", + "type": "integer", + "minimum": 1 + } + } + }, + "SignedIdentifier": { + "description": "signed identifier", + "type": "object", + "required": [ + "Id", + "AccessPolicy" + ], + "properties": { + "Id": { + "type": "string", + "description": "a unique id" + }, + "AccessPolicy": { + "$ref": "#/definitions/AccessPolicy" + } + } + }, + "SignedIdentifiers": { + "description": "a collection of signed identifiers", + "type": "array", + "items": { + "$ref": "#/definitions/SignedIdentifier" + }, + "xml": { + "wrapped": true, + "name": "SignedIdentifiers" + } + }, + "StaticWebsite": { + "description": "The properties that enable an account to host a static website", + "type": "object", + "required": [ + "Enabled" + ], + "properties": { + "Enabled": { + "description": "Indicates whether this account is hosting a static website", + "type": "boolean" + }, + "IndexDocument": { + "description": "The default name of the index page under each directory", + "type": "string" + }, + "ErrorDocument404Path": { + "description": "The absolute path of the custom 404 page", + "type": "string" + } + } + }, + "StorageServiceProperties": { + "description": "Storage Service Properties.", + "type": "object", + "properties": { + "Logging": { + "$ref": "#/definitions/Logging" + }, + "HourMetrics": { + "$ref": "#/definitions/Metrics" + }, + "MinuteMetrics": { + "$ref": "#/definitions/Metrics" + }, + "Cors": { + "description": "The set of CORS rules.", + "type": "array", + "items": { + "$ref": "#/definitions/CorsRule" + }, + "xml": { + "wrapped": true + } + }, + "DefaultServiceVersion": { + "description": "The default version to use for requests to the Blob service if an incoming request's version is not specified. Possible values include version 2008-10-27 and all more recent versions", + "type": "string" + }, + "DeleteRetentionPolicy": { + "$ref": "#/definitions/RetentionPolicy" + }, + "StaticWebsite": { + "$ref": "#/definitions/StaticWebsite" + } + } + }, + "StorageServiceStats": { + "description": "Stats for the storage service.", + "type": "object", + "properties": { + "GeoReplication": { + "$ref": "#/definitions/GeoReplication" + } + } + } + }, + "parameters": { + "Url": { + "name": "url", + "description": "The URL of the service account, container, or blob that is the targe of the desired operation.", + "required": true, + "type": "string", + "in": "path", + "x-ms-skip-url-encoding": true + }, + "ApiVersionParameter": { + "name": "x-ms-version", + "x-ms-client-name": "version", + "in": "header", + "required": true, + "type": "string", + "description": "Specifies the version of the operation to use for this request.", + "enum": [ + "2018-11-09" + ] + }, + "Blob": { + "name": "blob", + "in": "path", + "required": true, + "type": "string", + "pattern": "^[a-zA-Z0-9]+(?:/[a-zA-Z0-9]+)*(?:\\.[a-zA-Z0-9]+){0,1}$", + "minLength": 1, + "maxLength": 1024, + "x-ms-parameter-location": "client", + "description": "The blob name." + }, + "BlobCacheControl": { + "name": "x-ms-blob-cache-control", + "x-ms-client-name": "blobCacheControl", + "in": "header", + "required": false, + "type": "string", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "blob-HTTP-headers" + }, + "description": "Optional. Sets the blob's cache control. If specified, this property is stored with the blob and returned with a read request." + }, + "BlobConditionAppendPos": { + "name": "x-ms-blob-condition-appendpos", + "x-ms-client-name": "appendPosition", + "in": "header", + "required": false, + "type": "integer", + "format": "int64", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "append-position-access-conditions" + }, + "description": "Optional conditional header, used only for the Append Block operation. A number indicating the byte offset to compare. Append Block will succeed only if the append position is equal to this number. If it is not, the request will fail with the AppendPositionConditionNotMet error (HTTP status code 412 - Precondition Failed)." + }, + "BlobConditionMaxSize": { + "name": "x-ms-blob-condition-maxsize", + "x-ms-client-name": "maxSize", + "in": "header", + "required": false, + "type": "integer", + "format": "int64", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "append-position-access-conditions" + }, + "description": "Optional conditional header. The max length in bytes permitted for the append blob. If the Append Block operation would cause the blob to exceed that limit or if the blob size is already greater than the value specified in this header, the request will fail with MaxBlobSizeConditionNotMet error (HTTP status code 412 - Precondition Failed)." + }, + "BlobPublicAccess": { + "name": "x-ms-blob-public-access", + "x-ms-client-name": "access", + "in": "header", + "required": false, + "x-ms-parameter-location": "method", + "description": "Specifies whether data in the container may be accessed publicly and the level of access", + "type": "string", + "enum": [ + "container", + "blob" + ], + "x-ms-enum": { + "name": "PublicAccessType", + "modelAsString": true + } + }, + "AccessTier": { + "name": "x-ms-access-tier", + "x-ms-client-name": "tier", + "in": "header", + "required": true, + "type": "string", + "enum": [ + "P4", + "P6", + "P10", + "P20", + "P30", + "P40", + "P50", + "Hot", + "Cool", + "Archive" + ], + "x-ms-enum": { + "name": "AccessTier", + "modelAsString": true + }, + "x-ms-parameter-location": "method", + "description": "Indicates the tier to be set on the blob." + }, + "BlobContentDisposition": { + "name": "x-ms-blob-content-disposition", + "x-ms-client-name": "blobContentDisposition", + "in": "header", + "required": false, + "type": "string", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "blob-HTTP-headers" + }, + "description": "Optional. Sets the blob's Content-Disposition header." + }, + "BlobContentEncoding": { + "name": "x-ms-blob-content-encoding", + "x-ms-client-name": "blobContentEncoding", + "in": "header", + "required": false, + "type": "string", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "blob-HTTP-headers" + }, + "description": "Optional. Sets the blob's content encoding. If specified, this property is stored with the blob and returned with a read request." + }, + "BlobContentLanguage": { + "name": "x-ms-blob-content-language", + "x-ms-client-name": "blobContentLanguage", + "in": "header", + "required": false, + "type": "string", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "blob-HTTP-headers" + }, + "description": "Optional. Set the blob's content language. If specified, this property is stored with the blob and returned with a read request." + }, + "BlobContentLengthOptional": { + "name": "x-ms-blob-content-length", + "x-ms-client-name": "blobContentLength", + "in": "header", + "required": false, + "type": "integer", + "format": "int64", + "x-ms-parameter-location": "method", + "description": "This header specifies the maximum size for the page blob, up to 1 TB. The page blob size must be aligned to a 512-byte boundary." + }, + "BlobContentLengthRequired": { + "name": "x-ms-blob-content-length", + "x-ms-client-name": "blobContentLength", + "in": "header", + "required": true, + "type": "integer", + "format": "int64", + "x-ms-parameter-location": "method", + "description": "This header specifies the maximum size for the page blob, up to 1 TB. The page blob size must be aligned to a 512-byte boundary." + }, + "BlobContentMD5": { + "name": "x-ms-blob-content-md5", + "x-ms-client-name": "blobContentMD5", + "in": "header", + "required": false, + "type": "string", + "format": "byte", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "blob-HTTP-headers" + }, + "description": "Optional. An MD5 hash of the blob content. Note that this hash is not validated, as the hashes for the individual blocks were validated when each was uploaded." + }, + "BlobContentType": { + "name": "x-ms-blob-content-type", + "x-ms-client-name": "blobContentType", + "in": "header", + "required": false, + "type": "string", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "blob-HTTP-headers" + }, + "description": "Optional. Sets the blob's content type. If specified, this property is stored with the blob and returned with a read request." + }, + "BlobSequenceNumber": { + "name": "x-ms-blob-sequence-number", + "x-ms-client-name": "blobSequenceNumber", + "in": "header", + "required": false, + "type": "integer", + "format": "int64", + "default": 0, + "x-ms-parameter-location": "method", + "description": "Set for page blobs only. The sequence number is a user-controlled value that you can use to track requests. The value of the sequence number must be between 0 and 2^63 - 1." + }, + "BlockId": { + "name": "blockid", + "x-ms-client-name": "blockId", + "in": "query", + "type": "string", + "required": true, + "x-ms-parameter-location": "method", + "description": "A valid Base64 string value that identifies the block. Prior to encoding, the string must be less than or equal to 64 bytes in size. For a given blob, the length of the value specified for the blockid parameter must be the same size for each block." + }, + "BlockListType": { + "name": "blocklisttype", + "x-ms-client-name": "listType", + "in": "query", + "required": true, + "default": "committed", + "x-ms-parameter-location": "method", + "description": "Specifies whether to return the list of committed blocks, the list of uncommitted blocks, or both lists together.", + "type": "string", + "enum": [ + "committed", + "uncommitted", + "all" + ], + "x-ms-enum": { + "name": "BlockListType", + "modelAsString": false + } + }, + "Body": { + "name": "body", + "in": "body", + "required": true, + "schema": { + "type": "object", + "format": "file" + }, + "x-ms-parameter-location": "method", + "description": "Initial data" + }, + "CacheControl": { + "name": "Cache-Control", + "x-ms-client-name": "cacheControl", + "in": "header", + "required": false, + "type": "string", + "x-ms-parameter-location": "method", + "description": "Cache control for given resource" + }, + "ContainerAcl": { + "name": "containerAcl", + "in": "body", + "schema": { + "$ref": "#/definitions/SignedIdentifiers" + }, + "x-ms-parameter-location": "method", + "description": "the acls for the container" + }, + "CopyId": { + "name": "copyid", + "x-ms-client-name": "copyId", + "in": "query", + "required": true, + "type": "string", + "x-ms-parameter-location": "method", + "description": "The copy identifier provided in the x-ms-copy-id header of the original Copy Blob operation." + }, + "ClientRequestId": { + "name": "x-ms-client-request-id", + "x-ms-client-name": "requestId", + "in": "header", + "required": false, + "type": "string", + "x-ms-parameter-location": "method", + "description": "Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage analytics logging is enabled." + }, + "ContainerName": { + "name": "containerName", + "in": "path", + "required": true, + "type": "string", + "x-ms-parameter-location": "client", + "description": "The container name." + }, + "ContentCrc64": { + "name": "x-ms-content-crc64", + "x-ms-client-name": "transactionalContentCrc64", + "in": "header", + "required": false, + "type": "string", + "format": "byte", + "x-ms-parameter-location": "method", + "description": "Specify the transactional crc64 for the body, to be validated by the service." + }, + "ContentLength": { + "name": "Content-Length", + "in": "header", + "required": true, + "type": "integer", + "format": "int64", + "x-ms-parameter-location": "method", + "description": "The length of the request." + }, + "ContentMD5": { + "name": "Content-MD5", + "x-ms-client-name": "transactionalContentMD5", + "in": "header", + "required": false, + "type": "string", + "format": "byte", + "x-ms-parameter-location": "method", + "description": "Specify the transactional md5 for the body, to be validated by the service." + }, + "CopySource": { + "name": "x-ms-copy-source", + "x-ms-client-name": "copySource", + "in": "header", + "required": true, + "type": "string", + "format": "url", + "x-ms-parameter-location": "method", + "description": "Specifies the name of the source page blob snapshot. This value is a URL of up to 2 KB in length that specifies a page blob snapshot. The value should be URL-encoded as it would appear in a request URI. The source blob must either be public or must be authenticated via a shared access signature." + }, + "DeleteSnapshots": { + "name": "x-ms-delete-snapshots", + "x-ms-client-name": "deleteSnapshots", + "description": "Required if the blob has associated snapshots. Specify one of the following two options: include: Delete the base blob and all of its snapshots. only: Delete only the blob's snapshots and not the blob itself", + "x-ms-parameter-location": "method", + "in": "header", + "required": false, + "type": "string", + "enum": [ + "include", + "only" + ], + "x-ms-enum": { + "name": "DeleteSnapshotsOptionType", + "modelAsString": false + } + }, + "Delimiter": { + "name": "delimiter", + "description": "When the request includes this parameter, the operation returns a BlobPrefix element in the response body that acts as a placeholder for all blobs whose names begin with the same substring up to the appearance of the delimiter character. The delimiter may be a single character or a string.", + "type": "string", + "x-ms-parameter-location": "method", + "in": "query", + "required": true + }, + "EncryptionKey": { + "name": "x-ms-encryption-key", + "x-ms-client-name": "EncryptionKey", + "type": "string", + "in": "query", + "required": false, + "x-ms-parameter-location": "method", + "description": "Optional. Specifies the encryption key to use to encrypt the data provided in the request. If not specified, encryption is performed with the root account encryption key. For more information, see Encryption at Rest for Azure Storage Services." + }, + "EncryptionKeySha256": { + "name": "x-ms-encryption-key-sha256", + "x-ms-client-name": "encryptionKeySha256", + "type": "string", + "in": "query", + "required": false, + "x-ms-parameter-location": "method", + "description": "The SHA-256 hash of the provided encryption key. Must be provided if the x-ms-encryption-key header is provided." + }, + "EncryptionAlgorithm": { + "name": "x-ms-encryption-algorithm", + "x-ms-client-name": "EncryptionAlgorithm", + "type": "string", + "in": "query", + "required": false, + "enum": [ + "AES256" + ], + "x-ms-enum": { + "name": "EncryptionAlgorithmType", + "modelAsString": false + }, + "x-ms-parameter-location": "method", + "description": "The algorithm used to produce the encryption key hash. Currently, the only accepted value is \"AES256\". Must be provided if the x-ms-encryption-key header is provided." + }, + "GetRangeContentMD5": { + "name": "x-ms-range-get-content-md5", + "x-ms-client-name": "rangeGetContentMD5", + "in": "header", + "required": false, + "type": "boolean", + "x-ms-parameter-location": "method", + "description": "When set to true and specified together with the Range, the service returns the MD5 hash for the range, as long as the range is less than or equal to 4 MB in size." + }, + "IfMatch": { + "name": "If-Match", + "x-ms-client-name": "ifMatch", + "in": "header", + "required": false, + "type": "string", + "format": "etag", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "modified-access-conditions" + }, + "description": "Specify an ETag value to operate only on blobs with a matching value." + }, + "IfModifiedSince": { + "name": "If-Modified-Since", + "x-ms-client-name": "ifModifiedSince", + "in": "header", + "required": false, + "type": "string", + "format": "date-time-rfc1123", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "modified-access-conditions" + }, + "description": "Specify this header value to operate only on a blob if it has been modified since the specified date/time." + }, + "IfNoneMatch": { + "name": "If-None-Match", + "x-ms-client-name": "ifNoneMatch", + "in": "header", + "required": false, + "type": "string", + "format": "etag", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "modified-access-conditions" + }, + "description": "Specify an ETag value to operate only on blobs without a matching value." + }, + "IfUnmodifiedSince": { + "name": "If-Unmodified-Since", + "x-ms-client-name": "ifUnmodifiedSince", + "in": "header", + "required": false, + "type": "string", + "format": "date-time-rfc1123", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "modified-access-conditions" + }, + "description": "Specify this header value to operate only on a blob if it has not been modified since the specified date/time." + }, + "IfSequenceNumberEqualTo": { + "name": "x-ms-if-sequence-number-eq", + "x-ms-client-name": "ifSequenceNumberEqualTo", + "in": "header", + "required": false, + "type": "integer", + "format": "int64", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "sequence-number-access-conditions" + }, + "description": "Specify this header value to operate only on a blob if it has the specified sequence number." + }, + "IfSequenceNumberLessThan": { + "name": "x-ms-if-sequence-number-lt", + "x-ms-client-name": "ifSequenceNumberLessThan", + "in": "header", + "required": false, + "type": "integer", + "format": "int64", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "sequence-number-access-conditions" + }, + "description": "Specify this header value to operate only on a blob if it has a sequence number less than the specified." + }, + "IfSequenceNumberLessThanOrEqualTo": { + "name": "x-ms-if-sequence-number-le", + "x-ms-client-name": "ifSequenceNumberLessThanOrEqualTo", + "in": "header", + "required": false, + "type": "integer", + "format": "int64", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "sequence-number-access-conditions" + }, + "description": "Specify this header value to operate only on a blob if it has a sequence number less than or equal to the specified." + }, + "KeyInfo": { + "name": "KeyInfo", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/KeyInfo" + } + }, + "ListBlobsInclude": { + "name": "include", + "in": "query", + "required": false, + "type": "array", + "collectionFormat": "csv", + "items": { + "type": "string", + "enum": [ + "copy", + "deleted", + "metadata", + "snapshots", + "uncommittedblobs" + ], + "x-ms-enum": { + "name": "ListBlobsIncludeItem", + "modelAsString": false + } + }, + "x-ms-parameter-location": "method", + "description": "Include this parameter to specify one or more datasets to include in the response." + }, + "ListContainersInclude": { + "name": "include", + "in": "query", + "required": false, + "type": "string", + "enum": [ + "metadata" + ], + "x-ms-enum": { + "name": "ListContainersIncludeType", + "modelAsString": false + }, + "x-ms-parameter-location": "method", + "description": "Include this parameter to specify that the container's metadata be returned as part of the response body." + }, + "LeaseBreakPeriod": { + "name": "x-ms-lease-break-period", + "x-ms-client-name": "breakPeriod", + "in": "header", + "required": false, + "type": "integer", + "x-ms-parameter-location": "method", + "description": "For a break operation, proposed duration the lease should continue before it is broken, in seconds, between 0 and 60. This break period is only used if it is shorter than the time remaining on the lease. If longer, the time remaining on the lease is used. A new lease will not be available before the break period has expired, but the lease may be held for longer than the break period. If this header does not appear with a break operation, a fixed-duration lease breaks after the remaining lease period elapses, and an infinite lease breaks immediately." + }, + "LeaseDuration": { + "name": "x-ms-lease-duration", + "x-ms-client-name": "duration", + "in": "header", + "required": false, + "type": "integer", + "x-ms-parameter-location": "method", + "description": "Specifies the duration of the lease, in seconds, or negative one (-1) for a lease that never expires. A non-infinite lease can be between 15 and 60 seconds. A lease duration cannot be changed using renew or change." + }, + "LeaseIdOptional": { + "name": "x-ms-lease-id", + "x-ms-client-name": "leaseId", + "in": "header", + "required": false, + "type": "string", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "lease-access-conditions" + }, + "description": "If specified, the operation only succeeds if the resource's lease is active and matches this ID." + }, + "LeaseIdRequired": { + "name": "x-ms-lease-id", + "x-ms-client-name": "leaseId", + "in": "header", + "required": true, + "type": "string", + "x-ms-parameter-location": "method", + "description": "Specifies the current lease ID on the resource." + }, + "Marker": { + "name": "marker", + "in": "query", + "required": false, + "type": "string", + "description": "A string value that identifies the portion of the list of containers to be returned with the next listing operation. The operation returns the NextMarker value within the response body if the listing operation did not return all containers remaining to be listed with the current page. The NextMarker value can be used as the value for the marker parameter in a subsequent call to request the next page of list items. The marker value is opaque to the client.", + "x-ms-parameter-location": "method" + }, + "MaxResults": { + "name": "maxresults", + "in": "query", + "required": false, + "type": "integer", + "minimum": 1, + "x-ms-parameter-location": "method", + "description": "Specifies the maximum number of containers to return. If the request does not specify maxresults, or specifies a value greater than 5000, the server will return up to 5000 items. Note that if the listing operation crosses a partition boundary, then the service will return a continuation token for retrieving the remainder of the results. For this reason, it is possible that the service will return fewer results than specified by maxresults, or than the default of 5000." + }, + "Metadata": { + "name": "x-ms-meta", + "x-ms-client-name": "metadata", + "in": "header", + "required": false, + "type": "string", + "x-ms-parameter-location": "method", + "description": "Optional. Specifies a user-defined name-value pair associated with the blob. If no name-value pairs are specified, the operation will copy the metadata from the source blob or file to the destination blob. If one or more name-value pairs are specified, the destination blob is created with the specified metadata, and metadata is not copied from the source blob or file. Note that beginning with version 2009-09-19, metadata names must adhere to the naming rules for C# identifiers. See Naming and Referencing Containers, Blobs, and Metadata for more information.", + "x-ms-header-collection-prefix": "x-ms-meta-" + }, + "Prefix": { + "name": "prefix", + "in": "query", + "required": false, + "type": "string", + "description": "Filters the results to return only containers whose name begins with the specified prefix.", + "x-ms-parameter-location": "method" + }, + "PrevSnapshot": { + "name": "prevsnapshot", + "in": "query", + "required": false, + "type": "string", + "x-ms-parameter-location": "method", + "description": "Optional in version 2015-07-08 and newer. The prevsnapshot parameter is a DateTime value that specifies that the response will contain only pages that were changed between target blob and previous snapshot. Changed pages include both updated and cleared pages. The target blob may be a snapshot, as long as the snapshot specified by prevsnapshot is the older of the two. Note that incremental snapshots are currently supported only for blobs created on or after January 1, 2016." + }, + "ProposedLeaseIdOptional": { + "name": "x-ms-proposed-lease-id", + "x-ms-client-name": "proposedLeaseId", + "in": "header", + "required": false, + "type": "string", + "x-ms-parameter-location": "method", + "description": "Proposed lease ID, in a GUID string format. The Blob service returns 400 (Invalid request) if the proposed lease ID is not in the correct format. See Guid Constructor (String) for a list of valid GUID string formats." + }, + "ProposedLeaseIdRequired": { + "name": "x-ms-proposed-lease-id", + "x-ms-client-name": "proposedLeaseId", + "in": "header", + "required": true, + "type": "string", + "x-ms-parameter-location": "method", + "description": "Proposed lease ID, in a GUID string format. The Blob service returns 400 (Invalid request) if the proposed lease ID is not in the correct format. See Guid Constructor (String) for a list of valid GUID string formats." + }, + "Range": { + "name": "x-ms-range", + "x-ms-client-name": "range", + "in": "header", + "required": false, + "type": "string", + "x-ms-parameter-location": "method", + "description": "Return only the bytes of the blob in the specified range." + }, + "RangeRequiredPutPageFromUrl": { + "name": "x-ms-range", + "x-ms-client-name": "range", + "in": "header", + "required": true, + "type": "string", + "x-ms-parameter-location": "method", + "description": "The range of bytes to which the source range would be written. The range should be 512 aligned and range-end is required." + }, + "SequenceNumberAction": { + "name": "x-ms-sequence-number-action", + "x-ms-client-name": "sequenceNumberAction", + "in": "header", + "required": true, + "x-ms-parameter-location": "method", + "description": "Required if the x-ms-blob-sequence-number header is set for the request. This property applies to page blobs only. This property indicates how the service should modify the blob's sequence number", + "type": "string", + "enum": [ + "max", + "update", + "increment" + ], + "x-ms-enum": { + "name": "SequenceNumberActionType", + "modelAsString": false + } + }, + "Snapshot": { + "name": "snapshot", + "in": "query", + "required": false, + "type": "string", + "x-ms-parameter-location": "method", + "description": "The snapshot parameter is an opaque DateTime value that, when present, specifies the blob snapshot to retrieve. For more information on working with blob snapshots, see Creating a Snapshot of a Blob." + }, + "SourceContentMD5": { + "name": "x-ms-source-content-md5", + "x-ms-client-name": "sourceContentMD5", + "in": "header", + "required": false, + "type": "string", + "format": "byte", + "x-ms-parameter-location": "method", + "description": "Specify the md5 calculated for the range of bytes that must be read from the copy source." + }, + "SourceRange": { + "name": "x-ms-source-range", + "x-ms-client-name": "sourceRange", + "in": "header", + "required": false, + "type": "string", + "x-ms-parameter-location": "method", + "description": "Bytes of source data in the specified range." + }, + "SourceRangeRequiredPutPageFromUrl": { + "name": "x-ms-source-range", + "x-ms-client-name": "sourceRange", + "in": "header", + "required": true, + "type": "string", + "x-ms-parameter-location": "method", + "description": "Bytes of source data in the specified range. The length of this range should match the ContentLength header and x-ms-range/Range destination range header." + }, + "SourceIfMatch": { + "name": "x-ms-source-if-match", + "x-ms-client-name": "sourceIfMatch", + "in": "header", + "required": false, + "type": "string", + "format": "etag", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "source-modified-access-conditions" + }, + "description": "Specify an ETag value to operate only on blobs with a matching value." + }, + "SourceIfModifiedSince": { + "name": "x-ms-source-if-modified-since", + "x-ms-client-name": "sourceIfModifiedSince", + "in": "header", + "required": false, + "type": "string", + "format": "date-time-rfc1123", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "source-modified-access-conditions" + }, + "description": "Specify this header value to operate only on a blob if it has been modified since the specified date/time." + }, + "SourceIfNoneMatch": { + "name": "x-ms-source-if-none-match", + "x-ms-client-name": "sourceIfNoneMatch", + "in": "header", + "required": false, + "type": "string", + "format": "etag", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "source-modified-access-conditions" + }, + "description": "Specify an ETag value to operate only on blobs without a matching value." + }, + "SourceIfUnmodifiedSince": { + "name": "x-ms-source-if-unmodified-since", + "x-ms-client-name": "sourceIfUnmodifiedSince", + "in": "header", + "required": false, + "type": "string", + "format": "date-time-rfc1123", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "source-modified-access-conditions" + }, + "description": "Specify this header value to operate only on a blob if it has not been modified since the specified date/time." + }, + "SourceLeaseId": { + "name": "x-ms-source-lease-id", + "x-ms-client-name": "sourceLeaseId", + "in": "header", + "required": false, + "type": "string", + "x-ms-parameter-location": "method", + "description": "A lease ID for the source path. If specified, the source path must have an active lease and the leaase ID must match." + }, + "SourceUrl": { + "name": "x-ms-copy-source", + "x-ms-client-name": "sourceUrl", + "in": "header", + "required": true, + "type": "string", + "format": "url", + "x-ms-parameter-location": "method", + "description": "Specify a URL to the copy source." + }, + "StorageServiceProperties": { + "name": "StorageServiceProperties", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/StorageServiceProperties" + }, + "x-ms-parameter-location": "method", + "description": "The StorageService properties." + }, + "Timeout": { + "name": "timeout", + "in": "query", + "required": false, + "type": "integer", + "minimum": 0, + "x-ms-parameter-location": "method", + "description": "The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations." + }, + "VersionId": { + "name": "versionid", + "x-ms-client-name": "versionId", + "in": "query", + "required": false, + "type": "string", + "x-ms-parameter-location": "method", + "description": "The version ID parameter is an opaque DateTime value that, when present, specifies the blob version to retrieve." + }, + "XMsCacheControl": { + "name": "x-ms-cache-control", + "x-ms-client-name": "cacheControl", + "in": "header", + "required": false, + "type": "string", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "directory-http-headers" + }, + "description": "Cache control for given resource" + }, + "XMsContentType": { + "name": "x-ms-content-type", + "x-ms-client-name": "contentType", + "in": "header", + "required": false, + "type": "string", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "directory-http-headers" + }, + "description": "Content type for given resource" + }, + "XMsContentEncoding": { + "name": "x-ms-content-encoding", + "x-ms-client-name": "contentEncoding", + "in": "header", + "required": false, + "type": "string", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "directory-http-headers" + }, + "description": "Content encoding for given resource" + }, + "XMsContentLanguage": { + "name": "x-ms-content-language", + "x-ms-client-name": "contentLanguage", + "in": "header", + "required": false, + "type": "string", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "directory-http-headers" + }, + "description": "Content language for given resource" + }, + "XMsContentDisposition": { + "name": "x-ms-content-disposition", + "x-ms-client-name": "contentDisposition", + "in": "header", + "required": false, + "type": "string", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "directory-http-headers" + }, + "description": "Content disposition for given resource" + } + } +} \ No newline at end of file diff --git a/storage/client/file/swagger/file.json b/storage/client/file/swagger/file.json new file mode 100644 index 0000000000000..06240e4359346 --- /dev/null +++ b/storage/client/file/swagger/file.json @@ -0,0 +1,3616 @@ +{ + "swagger": "2.0", + "info": { + "title": "Azure File Storage", + "version": "2018-11-09", + "x-ms-code-generation-settings": { + "header": "MIT", + "strictSpecAdherence": false + } + }, + "x-ms-parameterized-host": { + "hostTemplate": "{url}", + "useSchemePrefix": false, + "positionInOperation": "first", + "parameters": [{ + "$ref": "#/parameters/Url" + }] + }, + "securityDefinitions": { + "File_shared_key": { + "type": "apiKey", + "name": "Authorization", + "in": "header" + } + }, + "schemes": [ + "https" + ], + "consumes": [ + "application/xml" + ], + "produces": [ + "application/xml" + ], + "paths": { + + }, + "x-ms-paths": { + "/?restype=service&comp=properties": { + "put": { + "tags": [ + "service" + ], + "operationId": "Service_SetProperties", + "description": "Sets properties for a storage account's File service endpoint, including properties for Storage Analytics metrics and CORS (Cross-Origin Resource Sharing) rules.", + "parameters": [{ + "$ref": "#/parameters/StorageServiceProperties" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "202": { + "description": "Success (Accepted)", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the File service used to execute the request." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "get": { + "tags": [ + "service" + ], + "operationId": "Service_GetProperties", + "description": "Gets the properties of a storage account's File service, including properties for Storage Analytics metrics and CORS (Cross-Origin Resource Sharing) rules.", + "parameters": [{ + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Success.", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the File service used to execute the request." + } + }, + "schema": { + "$ref": "#/definitions/StorageServiceProperties" + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [{ + "name": "restype", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "service" + ] + }, + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "properties" + ] + } + ] + }, + "/?comp=list": { + "get": { + "tags": [ + "service" + ], + "operationId": "Service_ListSharesSegment", + "description": "The List Shares Segment operation returns a list of the shares and share snapshots under the specified account.", + "parameters": [{ + "$ref": "#/parameters/Prefix" + }, + { + "$ref": "#/parameters/Marker" + }, + { + "$ref": "#/parameters/MaxResults" + }, + { + "$ref": "#/parameters/ListSharesInclude" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Success.", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the File service used to execute the request." + } + }, + "schema": { + "$ref": "#/definitions/ListSharesResponse" + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "NextMarker" + } + }, + "parameters": [{ + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "list" + ] + }] + }, + "/{shareName}?restype=share": { + "put": { + "tags": [ + "share" + ], + "operationId": "Share_Create", + "description": "Creates a new share under the specified account. If the share with the same name already exists, the operation fails.", + "parameters": [{ + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/Metadata" + }, + { + "$ref": "#/parameters/ShareQuota" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "201": { + "description": "Success, Share created.", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value which represents the version of the share, in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the share was last modified. Any operation that modifies the share or its properties or metadata updates the last modified time. Operations on files do not affect the last modified time of the share." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the File service used to execute the request." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "A UTC date/time value generated by the service that indicates the time at which the response was initiated." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "get": { + "tags": [ + "share" + ], + "operationId": "Share_GetProperties", + "description": "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.", + "parameters": [{ + "$ref": "#/parameters/ShareSnapshot" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "x-ms-meta": { + "type": "string", + "description": "A set of name-value pairs that contain the user-defined metadata of the share.", + "x-ms-client-name": "Metadata", + "x-ms-header-collection-prefix": "x-ms-meta-" + }, + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally, in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the share was last modified. Any operation that modifies the share or its properties updates the last modified time. Operations on files do not affect the last modified time of the share." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the File service used to execute the request." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "A UTC date/time value generated by the service that indicates the time at which the response was initiated." + }, + "x-ms-share-quota": { + "x-ms-client-name": "Quota", + "type": "integer", + "format": "int64", + "description": "Returns the current share quota in GB." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "delete": { + "tags": [ + "share" + ], + "operationId": "Share_Delete", + "description": "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.", + "parameters": [{ + "$ref": "#/parameters/ShareSnapshot" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/DeleteSnapshots" + } + ], + "responses": { + "202": { + "description": "Accepted", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the File service used to execute the request." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "A UTC date/time value generated by the service that indicates the time at which the response was initiated." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [{ + "name": "restype", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "share" + ] + }] + }, + "/{shareName}?restype=share&comp=snapshot": { + "put": { + "tags": [ + "share" + ], + "operationId": "Share_CreateSnapshot", + "description": "Creates a read-only snapshot of a share.", + "parameters": [{ + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/Metadata" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "201": { + "description": "Success, Share snapshot created.", + "headers": { + "x-ms-snapshot": { + "x-ms-client-name": "Snapshot", + "type": "string", + "description": "This header is a DateTime value that uniquely identifies the share snapshot. The value of this header may be used in subsequent requests to access the share snapshot. This value is opaque." + }, + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value which represents the version of the share snapshot, in quotes. A share snapshot cannot be modified, so the ETag of a given share snapshot never changes. However, if new metadata was supplied with the Snapshot Share request then the ETag of the share snapshot differs from that of the base share. If no metadata was specified with the request, the ETag of the share snapshot is identical to that of the base share at the time the share snapshot was taken." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the share was last modified. A share snapshot cannot be modified, so the last modified time of a given share snapshot never changes. However, if new metadata was supplied with the Snapshot Share request then the last modified time of the share snapshot differs from that of the base share. If no metadata was specified with the request, the last modified time of the share snapshot is identical to that of the base share at the time the share snapshot was taken." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the File service used to execute the request." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "A UTC date/time value generated by the service that indicates the time at which the response was initiated." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [{ + "name": "restype", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "share" + ] + }, + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "snapshot" + ] + } + ] + }, + "/{shareName}?restype=share&comp=properties": { + "put": { + "tags": [ + "share" + ], + "operationId": "Share_SetQuota", + "description": "Sets quota for the specified share.", + "parameters": [{ + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ShareQuota" + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally, in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the share was last modified. Any operation that modifies the share or its properties updates the last modified time. Operations on files do not affect the last modified time of the share." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the File service used to execute the request." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "A UTC date/time value generated by the service that indicates the time at which the response was initiated." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [{ + "name": "restype", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "share" + ] + }, + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "properties" + ] + } + ] + }, + "/{shareName}?restype=share&comp=metadata": { + "put": { + "tags": [ + "share" + ], + "operationId": "Share_SetMetadata", + "description": "Sets one or more user-defined name-value pairs for the specified share.", + "parameters": [{ + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/Metadata" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally, in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the share was last modified. Any operation that modifies the share or its properties updates the last modified time. Operations on files do not affect the last modified time of the share." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the File service used to execute the request." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "A UTC date/time value generated by the service that indicates the time at which the response was initiated." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [{ + "name": "restype", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "share" + ] + }, + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "metadata" + ] + } + ] + }, + "/{shareName}?restype=share&comp=acl": { + "get": { + "tags": [ + "share" + ], + "operationId": "Share_GetAccessPolicy", + "description": "Returns information about stored access policies specified on the share.", + "parameters": [{ + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally, in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the share was last modified. Any operation that modifies the share or its properties updates the last modified time. Operations on files do not affect the last modified time of the share." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the File service used to execute the request." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "A UTC date/time value generated by the service that indicates the time at which the response was initiated." + } + }, + "schema": { + "$ref": "#/definitions/SignedIdentifiers" + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "put": { + "tags": [ + "share" + ], + "operationId": "Share_SetAccessPolicy", + "description": "Sets a stored access policy for use with shared access signatures.", + "parameters": [{ + "$ref": "#/parameters/ShareAcl" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Success.", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally, in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the share was last modified. Any operation that modifies the share or its properties updates the last modified time. Operations on files do not affect the last modified time of the share." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the File service used to execute the request." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "A UTC date/time value generated by the service that indicates the time at which the response was initiated." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [{ + "name": "restype", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "share" + ] + }, + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "acl" + ] + } + ] + }, + "/{shareName}?restype=share&comp=stats": { + "get": { + "tags": [ + "share" + ], + "operationId": "Share_GetStatistics", + "description": "Retrieves statistics related to the share.", + "parameters": [{ + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally, in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the share was last modified. Any operation that modifies the share or its properties updates the last modified time. Operations on files do not affect the last modified time of the share." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the File service used to execute the request." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "A UTC date/time value generated by the service that indicates the time at which the response was initiated." + } + }, + "schema": { + "$ref": "#/definitions/ShareStats" + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [{ + "name": "restype", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "share" + ] + }, + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "stats" + ] + } + ] + }, + "/{shareName}/{directory}?restype=directory": { + "put": { + "tags": [ + "directory" + ], + "operationId": "Directory_Create", + "description": "Creates a new directory under the specified share or parent directory.", + "parameters": [{ + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/Metadata" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "201": { + "description": "Success, Directory created.", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value which represents the version of the directory, in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the share was last modified. Any operation that modifies the directory or its properties updates the last modified time. Operations on files do not affect the last modified time of the directory." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the File service used to execute the request." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "A UTC date/time value generated by the service that indicates the time at which the response was initiated." + }, + "x-ms-request-server-encrypted": { + "x-ms-client-name": "IsServerEncrypted", + "type": "boolean", + "description": "The value of this header is set to true if the contents of the request are successfully encrypted using the specified algorithm, and false otherwise." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "get": { + "tags": [ + "directory" + ], + "operationId": "Directory_GetProperties", + "description": "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.", + "parameters": [{ + "$ref": "#/parameters/ShareSnapshot" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Success.", + "headers": { + "x-ms-meta": { + "type": "string", + "description": "A set of name-value pairs that contain metadata for the directory.", + "x-ms-client-name": "Metadata", + "x-ms-header-collection-prefix": "x-ms-meta-" + }, + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally, in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the Directory was last modified. Operations on files within the directory do not affect the last modified time of the directory." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the File service used to execute the request." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "A UTC date/time value generated by the service that indicates the time at which the response was initiated." + }, + "x-ms-server-encrypted": { + "x-ms-client-name": "IsServerEncrypted", + "type": "boolean", + "description": "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." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "delete": { + "tags": [ + "directory" + ], + "operationId": "Directory_Delete", + "description": "Removes the specified empty directory. Note that the directory must be empty before it can be deleted.", + "parameters": [{ + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "202": { + "description": "Success (Accepted).", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the File service used to execute the request." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "A UTC date/time value generated by the service that indicates the time at which the response was initiated." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [{ + "name": "restype", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "directory" + ] + }] + }, + "/{shareName}/{directory}?restype=directory&comp=metadata": { + "put": { + "tags": [ + "directory" + ], + "operationId": "Directory_SetMetadata", + "description": "Updates user defined metadata for the specified directory.", + "parameters": [{ + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/Metadata" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Success (OK).", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value which represents the version of the directory, in quotes." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the File service used to execute the request." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "A UTC date/time value generated by the service that indicates the time at which the response was initiated." + }, + "x-ms-request-server-encrypted": { + "x-ms-client-name": "IsServerEncrypted", + "type": "boolean", + "description": "The value of this header is set to true if the contents of the request are successfully encrypted using the specified algorithm, and false otherwise." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [{ + "name": "restype", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "directory" + ] + }, + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "metadata" + ] + } + ] + }, + "/{shareName}/{directory}?restype=directory&comp=list": { + "get": { + "tags": [ + "directory" + ], + "operationId": "Directory_ListFilesAndDirectoriesSegment", + "description": "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.", + "parameters": [ + { + "$ref": "#/parameters/Prefix" + }, + { + "$ref": "#/parameters/ShareSnapshot" + }, + { + "$ref": "#/parameters/Marker" + }, + { + "$ref": "#/parameters/MaxResults" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Success.", + "headers": { + "Content-Type": { + "type": "string", + "description": "Specifies the format in which the results are returned. Currently this value is 'application/xml'." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the File service used to execute the request." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "A UTC date/time value generated by the service that indicates the time at which the response was initiated." + } + }, + "schema": { + "$ref": "#/definitions/ListFilesAndDirectoriesSegmentResponse" + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "NextMarker" + } + }, + "parameters": [{ + "name": "restype", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "directory" + ] + }, + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "list" + ] + } + ] + }, + "/{shareName}/{directory}?comp=listhandles": { + "get":{ + "tags": [ + "directory" + ], + "operationId": "Directory_ListHandles", + "description": "Lists handles for directory.", + "parameters":[ + { + "$ref": "#/parameters/Marker" + }, + { + "$ref": "#/parameters/MaxResults" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ShareSnapshot" + }, + { + "$ref": "#/parameters/Recursive" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Success.", + "headers": { + "Content-Type": { + "type": "string", + "description": "Specifies the format in which the results are returned. Currently this value is 'application/xml'." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the File service used to execute the request." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "A UTC date/time value generated by the service that indicates the time at which the response was initiated." + } + }, + "schema": { + "$ref": "#/definitions/ListHandlesResponse" + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [{ + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "listhandles" + ] + } + ] + }, + "/{shareName}/{directory}?comp=forceclosehandles": { + "put": { + "tags": [ + "directory" + ], + "operationId": "Directory_ForceCloseHandles", + "description": "Closes all handles open for given directory.", + "parameters": [ + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/Marker" + }, + { + "$ref": "#/parameters/ShareSnapshot" + }, + { + "$ref": "#/parameters/HandleId" + }, + { + "$ref": "#/parameters/Recursive" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Success.", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the File service used to execute the request." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "A UTC date/time value generated by the service that indicates the time at which the response was initiated." + }, + "x-ms-marker": { + "x-ms-client-name": "marker", + "type": "string", + "description": "A string describing next handle to be closed. It is returned when more handles need to be closed to complete the request." + }, + "x-ms-number-of-handles-closed": { + "x-ms-client-name": "numberOfHandlesClosed", + "type": "integer", + "description": "Contains count of number of handles closed." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [{ + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "forceclosehandles" + ] + } + ] + }, + "/{shareName}/{directory}/{fileName}": { + "put": { + "tags": [ + "file" + ], + "operationId": "File_Create", + "description": "Creates a new file or replaces a file. Note it only initializes the file with no content.", + "parameters": [{ + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "name": "x-ms-content-length", + "x-ms-client-name": "fileContentLength", + "in": "header", + "description": "Specifies the maximum size for the file, up to 1 TB.", + "required": true, + "type": "integer", + "format": "int64" + }, + { + "$ref": "#/parameters/FileType" + }, + { + "$ref": "#/parameters/FileContentType" + }, + { + "$ref": "#/parameters/FileContentEncoding" + }, + { + "$ref": "#/parameters/FileContentLanguage" + }, + { + "$ref": "#/parameters/FileCacheControl" + }, + { + "$ref": "#/parameters/FileContentMD5" + }, + { + "$ref": "#/parameters/FileContentDisposition" + }, + { + "$ref": "#/parameters/Metadata" + } + ], + "responses": { + "201": { + "description": "Success, File created.", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value which represents the version of the file, in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the share was last modified. Any operation that modifies the directory or its properties updates the last modified time. Operations on files do not affect the last modified time of the directory." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the File service used to execute the request." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "A UTC date/time value generated by the service that indicates the time at which the response was initiated." + }, + "x-ms-request-server-encrypted": { + "x-ms-client-name": "IsServerEncrypted", + "type": "boolean", + "description": "The value of this header is set to true if the contents of the request are successfully encrypted using the specified algorithm, and false otherwise." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "get": { + "tags": [ + "file" + ], + "operationId": "File_Download", + "description": "Reads or downloads a file from the system, including its metadata and properties.", + "parameters": [{ + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/Range" + }, + { + "$ref": "#/parameters/GetRangeContentMD5" + } + ], + "responses": { + "200": { + "description": "Succeeded to read the entire file.", + "headers": { + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the file was last modified. Any operation that modifies the file or its properties updates the last modified time." + }, + "x-ms-meta": { + "type": "string", + "description": "A set of name-value pairs associated with this file as user-defined metadata.", + "x-ms-client-name": "Metadata", + "x-ms-header-collection-prefix": "x-ms-meta-" + }, + "Content-Length": { + "type": "integer", + "format": "int64", + "description": "The number of bytes present in the response body." + }, + "Content-Type": { + "type": "string", + "description": "The content type specified for the file. The default content type is 'application/octet-stream'" + }, + "Content-Range": { + "type": "string", + "description": "Indicates the range of bytes returned if the client requested a subset of the file by setting the Range request header." + }, + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally, in quotes." + }, + "Content-MD5": { + "type": "string", + "format": "byte", + "description": "If the file has an MD5 hash and the request is to read the full file, this response header is returned so that the client can check for message content integrity. If the request is to read a specified range and the 'x-ms-range-get-content-md5' is set to true, then the request returns an MD5 hash for the range, as long as the range size is less than or equal to 4 MB. If neither of these sets of conditions is true, then no value is returned for the 'Content-MD5' header." + }, + "Content-Encoding": { + "type": "string", + "description": "Returns the value that was specified for the Content-Encoding request header." + }, + "Cache-Control": { + "type": "string", + "description": "Returned if it was previously specified for the file." + }, + "Content-Disposition": { + "type": "string", + "description": "Returns the value that was specified for the 'x-ms-content-disposition' header and specifies how to process the response." + }, + "Content-Language": { + "type": "string", + "description": "Returns the value that was specified for the Content-Language request header." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the File service used to execute the request." + }, + "Accept-Ranges": { + "type": "string", + "description": "Indicates that the service supports requests for partial file content." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "A UTC date/time value generated by the service that indicates the time at which the response was initiated." + }, + "x-ms-copy-completion-time": { + "x-ms-client-name": "CopyCompletionTime", + "type": "string", + "format": "date-time-rfc1123", + "description": "Conclusion time of the last attempted Copy File operation where this file was the destination file. This value can specify the time of a completed, aborted, or failed copy attempt." + }, + "x-ms-copy-status-description": { + "x-ms-client-name": "CopyStatusDescription", + "type": "string", + "description": "Only appears when x-ms-copy-status is failed or pending. Describes cause of fatal or non-fatal copy operation failure." + }, + "x-ms-copy-id": { + "x-ms-client-name": "CopyId", + "type": "string", + "description": "String identifier for the last attempted Copy File operation where this file was the destination file." + }, + "x-ms-copy-progress": { + "x-ms-client-name": "CopyProgress", + "type": "string", + "description": "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. Can show between 0 and Content-Length bytes copied." + }, + "x-ms-copy-source": { + "x-ms-client-name": "CopySource", + "type": "string", + "description": "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." + }, + "x-ms-copy-status": { + "x-ms-client-name": "CopyStatus", + "description": "State of the copy operation identified by 'x-ms-copy-id'.", + "type": "string", + "enum": [ + "pending", + "success", + "aborted", + "failed" + ], + "x-ms-enum": { + "name": "CopyStatusType", + "modelAsString": false + } + }, + "x-ms-content-md5": { + "x-ms-client-name": "FileContentMD5", + "type": "string", + "format": "byte", + "description": "If the file has a MD5 hash, and if request contains range header (Range or x-ms-range), this response header is returned with the value of the whole file's MD5 value. This value may or may not be equal to the value returned in Content-MD5 header, with the latter calculated from the requested range." + }, + "x-ms-server-encrypted": { + "x-ms-client-name": "IsServerEncrypted", + "type": "boolean", + "description": "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 (when the file is unencrypted, or if only parts of the file/application metadata are encrypted)." + } + }, + "schema": { + "type": "object", + "format": "file" + } + }, + "206": { + "description": "Succeeded to read a specified range of the file.", + "headers": { + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the file was last modified. Any operation that modifies the file or its properties updates the last modified time." + }, + "x-ms-meta": { + "type": "string", + "description": "A set of name-value pairs associated with this file as user-defined metadata.", + "x-ms-client-name": "Metadata", + "x-ms-header-collection-prefix": "x-ms-meta-" + }, + "Content-Length": { + "type": "integer", + "format": "int64", + "description": "The number of bytes present in the response body." + }, + "Content-Type": { + "type": "string", + "description": "The content type specified for the file. The default content type is 'application/octet-stream'" + }, + "Content-Range": { + "type": "string", + "description": "Indicates the range of bytes returned if the client requested a subset of the file by setting the Range request header." + }, + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally, in quotes." + }, + "Content-MD5": { + "type": "string", + "format": "byte", + "description": "If the file has an MD5 hash and the request is to read the full file, this response header is returned so that the client can check for message content integrity. If the request is to read a specified range and the 'x-ms-range-get-content-md5' is set to true, then the request returns an MD5 hash for the range, as long as the range size is less than or equal to 4 MB. If neither of these sets of conditions is true, then no value is returned for the 'Content-MD5' header." + }, + "Content-Encoding": { + "type": "string", + "description": "Returns the value that was specified for the Content-Encoding request header." + }, + "Cache-Control": { + "type": "string", + "description": "Returned if it was previously specified for the file." + }, + "Content-Disposition": { + "type": "string", + "description": "Returns the value that was specified for the 'x-ms-content-disposition' header and specifies how to process the response." + }, + "Content-Language": { + "type": "string", + "description": "Returns the value that was specified for the Content-Language request header." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the File service used to execute the request." + }, + "Accept-Ranges": { + "type": "string", + "description": "Indicates that the service supports requests for partial file content." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "A UTC date/time value generated by the service that indicates the time at which the response was initiated." + }, + "x-ms-copy-completion-time": { + "x-ms-client-name": "CopyCompletionTime", + "type": "string", + "format": "date-time-rfc1123", + "description": "Conclusion time of the last attempted Copy File operation where this file was the destination file. This value can specify the time of a completed, aborted, or failed copy attempt." + }, + "x-ms-copy-status-description": { + "x-ms-client-name": "CopyStatusDescription", + "type": "string", + "description": "Only appears when x-ms-copy-status is failed or pending. Describes cause of fatal or non-fatal copy operation failure." + }, + "x-ms-copy-id": { + "x-ms-client-name": "CopyId", + "type": "string", + "description": "String identifier for the last attempted Copy File operation where this file was the destination file." + }, + "x-ms-copy-progress": { + "x-ms-client-name": "CopyProgress", + "type": "string", + "description": "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. Can show between 0 and Content-Length bytes copied." + }, + "x-ms-copy-source": { + "x-ms-client-name": "CopySource", + "type": "string", + "description": "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." + }, + "x-ms-copy-status": { + "x-ms-client-name": "CopyStatus", + "description": "State of the copy operation identified by 'x-ms-copy-id'.", + "type": "string", + "enum": [ + "pending", + "success", + "aborted", + "failed" + ], + "x-ms-enum": { + "name": "CopyStatusType", + "modelAsString": false + } + }, + "x-ms-content-md5": { + "x-ms-client-name": "FileContentMD5", + "type": "string", + "format": "byte", + "description": "If the file has a MD5 hash, and if request contains range header (Range or x-ms-range), this response header is returned with the value of the whole file's MD5 value. This value may or may not be equal to the value returned in Content-MD5 header, with the latter calculated from the requested range." + }, + "x-ms-server-encrypted": { + "x-ms-client-name": "IsServerEncrypted", + "type": "boolean", + "description": "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 (when the file is unencrypted, or if only parts of the file/application metadata are encrypted)." + } + }, + "schema": { + "type": "object", + "format": "file" + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "head": { + "tags": [ + "file" + ], + "operationId": "File_GetProperties", + "description": "Returns all user-defined metadata, standard HTTP properties, and system properties for the file. It does not return the content of the file.", + "parameters": [{ + "$ref": "#/parameters/ShareSnapshot" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Success.", + "headers": { + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the file was last modified. The date format follows RFC 1123. Any operation that modifies the file or its properties updates the last modified time." + }, + "x-ms-meta": { + "type": "string", + "description": "A set of name-value pairs associated with this file as user-defined metadata.", + "x-ms-client-name": "Metadata", + "x-ms-header-collection-prefix": "x-ms-meta-" + }, + "x-ms-type": { + "x-ms-client-name": "FileType", + "description": "Returns the type File. Reserved for future use.", + "type": "string", + "enum": [ + "File" + ] + }, + "Content-Length": { + "type": "integer", + "format": "int64", + "description": "The size of the file in bytes. This header returns the value of the 'x-ms-content-length' header that is stored with the file." + }, + "Content-Type": { + "type": "string", + "description": "The content type specified for the file. The default content type is 'application/octet-stream'" + }, + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value that you can use to perform operations conditionally, in quotes." + }, + "Content-MD5": { + "type": "string", + "format": "byte", + "description": "If the Content-MD5 header has been set for the file, the Content-MD5 response header is returned so that the client can check for message content integrity." + }, + "Content-Encoding": { + "type": "string", + "description": "If the Content-Encoding request header has previously been set for the file, the Content-Encoding value is returned in this header." + }, + "Cache-Control": { + "type": "string", + "description": "If the Cache-Control request header has previously been set for the file, the Cache-Control value is returned in this header." + }, + "Content-Disposition": { + "type": "string", + "description": "Returns the value that was specified for the 'x-ms-content-disposition' header and specifies how to process the response." + }, + "Content-Language": { + "type": "string", + "description": "Returns the value that was specified for the Content-Language request header." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the File service used to execute the request." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "A UTC date/time value generated by the service that indicates the time at which the response was initiated." + }, + "x-ms-copy-completion-time": { + "x-ms-client-name": "CopyCompletionTime", + "type": "string", + "format": "date-time-rfc1123", + "description": "Conclusion time of the last attempted Copy File operation where this file was the destination file. This value can specify the time of a completed, aborted, or failed copy attempt." + }, + "x-ms-copy-status-description": { + "x-ms-client-name": "CopyStatusDescription", + "type": "string", + "description": "Only appears when x-ms-copy-status is failed or pending. Describes cause of fatal or non-fatal copy operation failure." + }, + "x-ms-copy-id": { + "x-ms-client-name": "CopyId", + "type": "string", + "description": "String identifier for the last attempted Copy File operation where this file was the destination file." + }, + "x-ms-copy-progress": { + "x-ms-client-name": "CopyProgress", + "type": "string", + "description": "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. Can show between 0 and Content-Length bytes copied." + }, + "x-ms-copy-source": { + "x-ms-client-name": "CopySource", + "type": "string", + "description": "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." + }, + "x-ms-copy-status": { + "x-ms-client-name": "CopyStatus", + "description": "State of the copy operation identified by 'x-ms-copy-id'.", + "type": "string", + "enum": [ + "pending", + "success", + "aborted", + "failed" + ], + "x-ms-enum": { + "name": "CopyStatusType", + "modelAsString": false + } + }, + "x-ms-server-encrypted": { + "x-ms-client-name": "IsServerEncrypted", + "type": "boolean", + "description": "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 (when the file is unencrypted, or if only parts of the file/application metadata are encrypted)." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + } + } + } + }, + "delete": { + "tags": [ + "file" + ], + "operationId": "File_Delete", + "description": "removes the file from the storage account.", + "parameters": [{ + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "202": { + "description": "Success (Accepted).", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the File service used to execute the request." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "A UTC date/time value generated by the service that indicates the time at which the response was initiated." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + + ] + }, + "/{shareName}/{directory}/{fileName}?comp=properties": { + "put": { + "tags": [ + "file" + ], + "operationId": "File_SetHTTPHeaders", + "description": "Sets HTTP headers on the file.", + "parameters": [{ + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "name": "x-ms-content-length", + "x-ms-client-name": "fileContentLength", + "in": "header", + "description": "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.", + "required": false, + "type": "integer", + "format": "int64" + }, + { + "$ref": "#/parameters/FileContentType" + }, + { + "$ref": "#/parameters/FileContentEncoding" + }, + { + "$ref": "#/parameters/FileContentLanguage" + }, + { + "$ref": "#/parameters/FileCacheControl" + }, + { + "$ref": "#/parameters/FileContentMD5" + }, + { + "$ref": "#/parameters/FileContentDisposition" + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value which represents the version of the file, in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the directory was last modified. Any operation that modifies the directory or its properties updates the last modified time. Operations on files do not affect the last modified time of the directory." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the File service used to execute the request." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "A UTC date/time value generated by the service that indicates the time at which the response was initiated." + }, + "x-ms-request-server-encrypted": { + "x-ms-client-name": "IsServerEncrypted", + "type": "boolean", + "description": "The value of this header is set to true if the contents of the request are successfully encrypted using the specified algorithm, and false otherwise." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [{ + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "properties" + ] + }] + }, + "/{shareName}/{directory}/{fileName}?comp=metadata": { + "put": { + "tags": [ + "file" + ], + "operationId": "File_SetMetadata", + "description": "Updates user-defined metadata for the specified file.", + "parameters": [{ + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/Metadata" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Success (OK).", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value which represents the version of the file, in quotes." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the File service used to execute the request." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "A UTC date/time value generated by the service that indicates the time at which the response was initiated." + }, + "x-ms-request-server-encrypted": { + "x-ms-client-name": "IsServerEncrypted", + "type": "boolean", + "description": "The value of this header is set to true if the contents of the request are successfully encrypted using the specified algorithm, and false otherwise." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [{ + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "metadata" + ] + }] + }, + "/{shareName}/{directory}/{fileName}?comp=range": { + "put": { + "tags": [ + "file" + ], + "operationId": "File_UploadRange", + "description": "Upload a range of bytes to a file.", + "consumes": [ + "application/octet-stream" + ], + "parameters": [{ + "$ref": "#/parameters/OptionalBody" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "name": "x-ms-range", + "x-ms-client-name": "range", + "in": "header", + "description": "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.", + "required": true, + "type": "string" + }, + { + "name": "x-ms-write", + "x-ms-client-name": "FileRangeWrite", + "in": "header", + "description": "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.", + "required": true, + "type": "string", + "enum": [ + "update", + "clear" + ], + "default": "update", + "x-ms-enum": { + "name": "FileRangeWriteType", + "modelAsString": false + } + }, + { + "$ref": "#/parameters/ContentLength" + }, + { + "$ref": "#/parameters/ContentMD5" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "201": { + "description": "Success (Created).", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value which represents the version of the file, in quotes." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the directory was last modified. Any operation that modifies the share or its properties or metadata updates the last modified time. Operations on files do not affect the last modified time of the share." + }, + "Content-MD5": { + "type": "string", + "format": "byte", + "description": "This header is returned so that the client can check for message content integrity. The value of this header is computed by the File service; it is not necessarily the same value as may have been specified in the request headers." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the File service used to execute the request." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "A UTC date/time value generated by the service that indicates the time at which the response was initiated." + }, + "x-ms-request-server-encrypted": { + "x-ms-client-name": "IsServerEncrypted", + "type": "boolean", + "description": "The value of this header is set to true if the contents of the request are successfully encrypted using the specified algorithm, and false otherwise." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [{ + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "range" + ] + }] + }, + "/{shareName}/{directory}/{fileName}?comp=rangelist": { + "get": { + "tags": [ + "file" + ], + "operationId": "File_GetRangeList", + "description": "Returns the list of valid ranges for a file.", + "parameters": [{ + "$ref": "#/parameters/ShareSnapshot" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "name": "x-ms-range", + "x-ms-client-name": "range", + "in": "header", + "description": "Specifies the range of bytes over which to list ranges, inclusively.", + "required": false, + "type": "string" + } + ], + "responses": { + "200": { + "description": "Success.", + "headers": { + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "The date/time that the file was last modified. Any operation that modifies the file, including an update of the file's metadata or properties, changes the file's last modified time." + }, + "ETag": { + "type": "string", + "format": "etag", + "description": "The ETag contains a value which represents the version of the file, in quotes." + }, + "x-ms-content-length": { + "x-ms-client-name": "FileContentLength", + "type": "integer", + "format": "int64", + "description": "The size of the file in bytes." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the File service used to execute the request." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "A UTC date/time value generated by the service that indicates the time at which the response was initiated." + } + }, + "schema": { + "$ref": "#/definitions/RangeList" + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [{ + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "rangelist" + ] + }] + }, + "/{shareName}/{directory}/{fileName}?comp=copy": { + "put": { + "tags": [ + "file" + ], + "operationId": "File_StartCopy", + "description": "Copies a blob or file to a destination file within the storage account.", + "parameters": [{ + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/Metadata" + }, + { + "$ref": "#/parameters/CopySource" + } + ], + "responses": { + "202": { + "description": "The copy file has been accepted with the specified copy status.", + "headers": { + "ETag": { + "type": "string", + "format": "etag", + "description": "If the copy is completed, contains the ETag of the destination file. If the copy is not complete, contains the ETag of the empty file created at the start of the copy." + }, + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date/time that the copy operation to the destination file completed." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the File service used to execute the request." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "A UTC date/time value generated by the service that indicates the time at which the response was initiated." + }, + "x-ms-copy-id": { + "x-ms-client-name": "CopyId", + "type": "string", + "description": "String identifier for this copy operation. Use with Get File or Get File Properties to check the status of this copy operation, or pass to Abort Copy File to abort a pending copy." + }, + "x-ms-copy-status": { + "x-ms-client-name": "CopyStatus", + "description": "State of the copy operation identified by x-ms-copy-id.", + "type": "string", + "enum": [ + "pending", + "success", + "aborted", + "failed" + ], + "x-ms-enum": { + "name": "CopyStatusType", + "modelAsString": false + } + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + + ] + }, + "/{shareName}/{directory}/{fileName}?comp=copy©id={CopyId}": { + "put": { + "tags": [ + "file" + ], + "operationId": "File_AbortCopy", + "description": "Aborts a pending Copy File operation, and leaves a destination file with zero length and full metadata.", + "parameters": [{ + "$ref": "#/parameters/CopyId" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/CopyActionAbort" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "204": { + "description": "The delete request was accepted and the file will be deleted.", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the File service used to execute the request." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "A UTC date/time value generated by the service that indicates the time at which the response was initiated." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [{ + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "copy" + ] + }] + }, + "/{shareName}/{directory}/{fileName}?comp=listhandles": { + "get":{ + "tags": [ + "file" + ], + "operationId": "File_ListHandles", + "description": "Lists handles for file", + "parameters":[ + { + "$ref": "#/parameters/Marker" + }, + { + "$ref": "#/parameters/MaxResults" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ShareSnapshot" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Success.", + "headers": { + "Content-Type": { + "type": "string", + "description": "Specifies the format in which the results are returned. Currently this value is 'application/xml'." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the File service used to execute the request." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "A UTC date/time value generated by the service that indicates the time at which the response was initiated." + } + }, + "schema": { + "$ref": "#/definitions/ListHandlesResponse" + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [{ + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "listhandles" + ] + } + ] + }, + "/{shareName}/{directory}/{fileName}?comp=forceclosehandles": { + "put": { + "tags": [ + "file" + ], + "operationId": "File_ForceCloseHandles", + "description": "Closes all handles open for given file", + "parameters": [ + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/Marker" + }, + { + "$ref": "#/parameters/ShareSnapshot" + }, + { + "$ref": "#/parameters/HandleId" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Success.", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the File service used to execute the request." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "A UTC date/time value generated by the service that indicates the time at which the response was initiated." + }, + "x-ms-marker": { + "x-ms-client-name": "marker", + "type": "string", + "description": "A string describing next handle to be closed. It is returned when more handles need to be closed to complete the request." + }, + "x-ms-number-of-handles-closed": { + "x-ms-client-name": "numberOfHandlesClosed", + "type": "integer", + "description": "Contains count of number of handles closed." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [{ + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "forceclosehandles" + ] + } + ] + } + }, + "definitions": { + "AccessPolicy": { + "description": "An Access policy.", + "type": "object", + "properties": { + "Start": { + "description": "The date-time the policy is active.", + "type": "string", + "format": "date-time" + }, + "Expiry": { + "description": "The date-time the policy expires.", + "type": "string", + "format": "date-time" + }, + "Permission": { + "description": "The permissions for the ACL policy.", + "type": "string" + } + } + }, + "CorsRule": { + "description": "CORS is an HTTP feature that enables a web application running under one domain to access resources in another domain. Web browsers implement a security restriction known as same-origin policy that prevents a web page from calling APIs in a different domain; CORS provides a secure way to allow one domain (the origin domain) to call APIs in another domain.", + "type": "object", + "required": [ + "AllowedOrigins", + "AllowedMethods", + "AllowedHeaders", + "ExposedHeaders", + "MaxAgeInSeconds" + ], + "properties": { + "AllowedOrigins": { + "description": "The origin domains that are permitted to make a request against the storage service via CORS. The origin domain is the domain from which the request originates. Note that the origin must be an exact case-sensitive match with the origin that the user age sends to the service. You can also use the wildcard character '*' to allow all origin domains to make requests via CORS.", + "type": "string" + }, + "AllowedMethods": { + "description": "The methods (HTTP request verbs) that the origin domain may use for a CORS request. (comma separated)", + "type": "string" + }, + "AllowedHeaders": { + "description": "The request headers that the origin domain may specify on the CORS request.", + "type": "string" + }, + "ExposedHeaders": { + "description": "The response headers that may be sent in the response to the CORS request and exposed by the browser to the request issuer.", + "type": "string" + }, + "MaxAgeInSeconds": { + "description": "The maximum amount time that a browser should cache the preflight OPTIONS request.", + "type": "integer", + "minimum": 0 + } + } + }, + "ErrorCode": { + "description": "Error codes returned by the service", + "type": "string", + "enum": [ + "AccountAlreadyExists", + "AccountBeingCreated", + "AccountIsDisabled", + "AuthenticationFailed", + "AuthorizationFailure", + "ConditionHeadersNotSupported", + "ConditionNotMet", + "EmptyMetadataKey", + "InsufficientAccountPermissions", + "InternalError", + "InvalidAuthenticationInfo", + "InvalidHeaderValue", + "InvalidHttpVerb", + "InvalidInput", + "InvalidMd5", + "InvalidMetadata", + "InvalidQueryParameterValue", + "InvalidRange", + "InvalidResourceName", + "InvalidUri", + "InvalidXmlDocument", + "InvalidXmlNodeValue", + "Md5Mismatch", + "MetadataTooLarge", + "MissingContentLengthHeader", + "MissingRequiredQueryParameter", + "MissingRequiredHeader", + "MissingRequiredXmlNode", + "MultipleConditionHeadersNotSupported", + "OperationTimedOut", + "OutOfRangeInput", + "OutOfRangeQueryParameterValue", + "RequestBodyTooLarge", + "ResourceTypeMismatch", + "RequestUrlFailedToParse", + "ResourceAlreadyExists", + "ResourceNotFound", + "ServerBusy", + "UnsupportedHeader", + "UnsupportedXmlNode", + "UnsupportedQueryParameter", + "UnsupportedHttpVerb", + "CannotDeleteFileOrDirectory", + "ClientCacheFlushDelay", + "DeletePending", + "DirectoryNotEmpty", + "FileLockConflict", + "InvalidFileOrDirectoryPathName", + "ParentNotFound", + "ReadOnlyAttribute", + "ShareAlreadyExists", + "ShareBeingDeleted", + "ShareDisabled", + "ShareNotFound", + "SharingViolation", + "ShareSnapshotInProgress", + "ShareSnapshotCountExceeded", + "ShareSnapshotOperationNotSupported", + "ShareHasSnapshots", + "ContainerQuotaDowngradeNotAllowed" + ], + "x-ms-enum": { + "name": "StorageErrorCode", + "modelAsString": true + } + }, + "FilesAndDirectoriesListSegment": { + "description": "Abstract for entries that can be listed from Directory.", + "type": "object", + "required": [ + "DirectoryItems", + "FileItems" + ], + "properties": { + "DirectoryItems": { + "type": "array", + "items": { + "$ref": "#/definitions/DirectoryItem" + } + }, + "FileItems": { + "type": "array", + "items": { + "$ref": "#/definitions/FileItem" + } + } + }, + "xml": { + "name": "Entries" + } + }, + "DirectoryItem": { + "xml": { + "name": "Directory" + }, + "description": "A listed directory item.", + "type": "object", + "required": [ + "Name" + ], + "properties": { + "Name": { + "type": "string" + } + } + }, + "FileItem": { + "xml": { + "name": "File" + }, + "description": "A listed file item.", + "type": "object", + "required": [ + "Name", + "Properties" + ], + "properties": { + "Name": { + "type": "string" + }, + "Properties": { + "$ref": "#/definitions/FileProperty" + } + } + }, + "FileProperty": { + "description": "File properties.", + "type": "object", + "required": [ + "Content-Length" + ], + "properties": { + "Content-Length": { + "description": "Content length of the file. This value may not be up-to-date since an SMB client may have modified the file locally. The value of Content-Length may not reflect that fact until the handle is closed or the op-lock is broken. To retrieve current property values, call Get File Properties.", + "type": "integer", + "format": "int64" + } + } + }, + "HandleItem" : { + "xml": { + "name": "Handle" + }, + "description": "A listed Azure Storage handle item.", + "type": "object", + "required": [ + "HandleId", + "Path", + "FileId", + "SessionId", + "ClientIp", + "OpenTime" + ], + "properties": { + "HandleId": { + "type": "string", + "description": "XSMB service handle ID" + }, + "Path": { + "type": "string", + "description": "File or directory name including full path starting from share root" + }, + "FileId": { + "type": "string", + "description": "FileId uniquely identifies the file or directory." + }, + "ParentId": { + "type": "string", + "description": "ParentId uniquely identifies the parent directory of the object." + }, + "SessionId": { + "type": "string", + "description": "SMB session ID in context of which the file handle was opened" + }, + "ClientIp": { + "type": "string", + "description": "Client IP that opened the handle" + }, + "OpenTime": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Time when the session that previously opened the handle has last been reconnected. (UTC)" + }, + "LastReconnectTime": { + "type": "string", + "format": "date-time-rfc1123", + "description": "Time handle was last connected to (UTC)" + } + } + }, + "ListFilesAndDirectoriesSegmentResponse": { + "xml": { + "name": "EnumerationResults" + }, + "description": "An enumeration of directories and files.", + "type": "object", + "required": [ + "ServiceEndpoint", + "ShareName", + "DirectoryPath", + "Prefix", + "NextMarker", + "Segment" + ], + "properties": { + "ServiceEndpoint": { + "type": "string", + "xml": { + "attribute": true + } + }, + "ShareName": { + "type": "string", + "xml": { + "attribute": true + } + }, + "ShareSnapshot": { + "type": "string", + "xml": { + "attribute": true + } + }, + "DirectoryPath": { + "type": "string", + "xml": { + "attribute": true + } + }, + "Prefix": { + "type": "string" + }, + "Marker": { + "type": "string" + }, + "MaxResults": { + "type": "integer" + }, + "Segment": { + "$ref": "#/definitions/FilesAndDirectoriesListSegment" + }, + "NextMarker": { + "type": "string" + } + } + }, + "ListHandlesResponse": { + "xml": { + "name": "EnumerationResults" + }, + "description": "An enumeration of handles.", + "type": "object", + "required": [ + "NextMarker" + ], + "properties": { + "HandleList": { + "type": "array", + "items": { + "$ref": "#/definitions/HandleItem" + }, + "xml": { + "name": "Entries", + "wrapped": true + } + }, + "NextMarker": { + "type": "string" + } + } + }, + "ListSharesResponse": { + "xml": { + "name": "EnumerationResults" + }, + "description": "An enumeration of shares.", + "type": "object", + "required": [ + "ServiceEndpoint", + "NextMarker" + ], + "properties": { + "ServiceEndpoint": { + "type": "string", + "xml": { + "attribute": true + } + }, + "Prefix": { + "type": "string" + }, + "Marker": { + "type": "string" + }, + "MaxResults": { + "type": "integer" + }, + "ShareItems": { + "type": "array", + "items": { + "$ref": "#/definitions/ShareItem" + }, + "xml": { + "name": "Shares", + "wrapped": true + } + }, + "NextMarker": { + "type": "string" + } + } + }, + "Metadata": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "Metrics": { + "description": "Storage Analytics metrics for file service.", + "required": [ + "Version", + "Enabled" + ], + "properties": { + "Version": { + "description": "The version of Storage Analytics to configure.", + "type": "string" + }, + "Enabled": { + "description": "Indicates whether metrics are enabled for the File service.", + "type": "boolean" + }, + "IncludeAPIs": { + "description": "Indicates whether metrics should generate summary statistics for called API operations.", + "type": "boolean" + }, + "RetentionPolicy": { + "$ref": "#/definitions/RetentionPolicy" + } + } + }, + "Range": { + "description": "An Azure Storage file range.", + "type": "object", + "required": [ + "Start", + "End" + ], + "properties": { + "Start": { + "type": "integer", + "format": "int64", + "description": "Start of the range." + }, + "End": { + "type": "integer", + "format": "int64", + "description": "End of the range." + } + }, + "xml": { + "name": "Range" + } + }, + "RangeList": { + "description": "A list of non-overlapping valid ranges, sorted by increasing address range.", + "type": "array", + "items": { + "$ref": "#/definitions/Range" + }, + "xml": { + "wrapped": true, + "name": "Ranges" + } + }, + "StorageError": { + "type": "object", + "properties": { + "Message": { + "type": "string" + } + } + }, + "RetentionPolicy": { + "description": "The retention policy.", + "type": "object", + "required": [ + "Enabled" + ], + "properties": { + "Enabled": { + "description": "Indicates whether a retention policy is enabled for the File service. If false, metrics data is retained, and the user is responsible for deleting it.", + "type": "boolean" + }, + "Days": { + "description": "Indicates the number of days that metrics data should be retained. All data older than this value will be deleted. Metrics data is deleted on a best-effort basis after the retention period expires.", + "type": "integer", + "minimum": 1, + "maximum": 365 + } + } + }, + "ShareItem": { + "xml": { + "name": "Share" + }, + "description": "A listed Azure Storage share item.", + "type": "object", + "required": [ + "Name", + "Properties" + ], + "properties": { + "Name": { + "type": "string" + }, + "Snapshot": { + "type": "string" + }, + "Properties": { + "$ref": "#/definitions/ShareProperties" + }, + "Metadata": { + "$ref": "#/definitions/Metadata" + } + } + }, + "ShareProperties": { + "description": "Properties of a share.", + "type": "object", + "required": [ + "Last-Modified", + "Etag", + "Quota" + ], + "properties": { + "Last-Modified": { + "type": "string", + "format": "date-time-rfc1123" + }, + "Etag": { + "type": "string", + "format": "etag" + }, + "Quota": { + "type": "integer", + "format": "int64", + } + } + }, + "ShareStats": { + "description": "Stats for the share.", + "type": "object", + "required": [ + "ShareUsageBytes" + ], + "properties": { + "ShareUsageBytes": { + "description": "The approximate size of the data stored in bytes, rounded up to the nearest gigabyte. Note that this value may not include all recently created or recently resized files.", + "type": "integer" + } + } + }, + "SignedIdentifier": { + "description": "Signed identifier.", + "type": "object", + "required": [ + "Id" + ], + "properties": { + "Id": { + "type": "string", + "description": "A unique id." + }, + "AccessPolicy": { + "description": "The access policy.", + "$ref": "#/definitions/AccessPolicy" + } + } + }, + "SignedIdentifiers": { + "description": "A collection of signed identifiers.", + "type": "array", + "items": { + "$ref": "#/definitions/SignedIdentifier", + "xml": { + "name": "SignedIdentifier" + } + }, + "xml": { + "wrapped": true, + "name": "SignedIdentifiers" + } + }, + "StorageServiceProperties": { + "description": "Storage service properties.", + "type": "object", + "properties": { + "HourMetrics": { + "description": "A summary of request statistics grouped by API in hourly aggregates for files.", + "$ref": "#/definitions/Metrics" + }, + "MinuteMetrics": { + "description": "A summary of request statistics grouped by API in minute aggregates for files.", + "$ref": "#/definitions/Metrics" + }, + "Cors": { + "description": "The set of CORS rules.", + "type": "array", + "items": { + "$ref": "#/definitions/CorsRule" + }, + "xml": { + "wrapped": true + } + } + } + } + }, + "parameters": { + "ApiVersionParameter": { + "name": "x-ms-version", + "x-ms-client-name": "version", + "in": "header", + "description": "Specifies the version of the operation to use for this request.", + "required": true, + "type": "string", + "enum": [ + "2018-11-09" + ] + }, + "ContentLength": { + "name": "Content-Length", + "x-ms-client-name": "contentLength", + "in": "header", + "description": "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.", + "required": true, + "type": "integer", + "format": "int64", + "x-ms-parameter-location": "method" + }, + "ContentMD5": { + "name": "Content-MD5", + "x-ms-client-name": "contentMD5", + "in": "header", + "description": "An MD5 hash of the content. This hash is used to verify the integrity of the data during transport. When the Content-MD5 header is specified, the File service compares the hash of the content that has arrived with the header value that was sent. If the two hashes do not match, the operation will fail with error code 400 (Bad Request).", + "required": false, + "type": "string", + "format": "byte", + "x-ms-parameter-location": "method" + }, + "CopyActionAbort": { + "name": "x-ms-copy-action", + "x-ms-client-name": "copyActionAbortConstant", + "in": "header", + "required": true, + "type": "string", + "enum": [ + "abort" + ], + "x-ms-parameter-location": "method" + }, + "CopyId": { + "name": "copyid", + "x-ms-client-name": "copyId", + "in": "query", + "required": true, + "type": "string", + "x-ms-parameter-location": "method", + "description": "The copy identifier provided in the x-ms-copy-id header of the original Copy File operation." + }, + "CopySource": { + "name": "x-ms-copy-source", + "x-ms-client-name": "copySource", + "in": "header", + "required": true, + "type": "string", + "x-ms-parameter-location": "method", + "description": "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." + }, + "DeleteSnapshots": { + "name": "x-ms-delete-snapshots", + "x-ms-client-name": "deleteSnapshots", + "description": "Specifies the option include to delete the base share and all of its snapshots.", + "in": "header", + "required": false, + "type": "string", + "enum": [ + "include" + ], + "x-ms-enum": { + "name": "DeleteSnapshotsOptionType", + "modelAsString": false + }, + "x-ms-parameter-location": "method" + }, + "FileCacheControl": { + "name": "x-ms-cache-control", + "x-ms-client-name": "fileCacheControl", + "description": "Sets the file's cache control. The File service stores this value but does not use or modify it.", + "in": "header", + "required": false, + "type": "string", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "file-HTTP-headers" + } + }, + "FileContentDisposition": { + "name": "x-ms-content-disposition", + "x-ms-client-name": "fileContentDisposition", + "description": "Sets the file's Content-Disposition header.", + "in": "header", + "required": false, + "type": "string", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "file-HTTP-headers" + } + }, + "FileContentEncoding": { + "name": "x-ms-content-encoding", + "x-ms-client-name": "fileContentEncoding", + "in": "header", + "description": "Specifies which content encodings have been applied to the file.", + "required": false, + "type": "string", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "file-HTTP-headers" + } + }, + "FileContentLanguage": { + "name": "x-ms-content-language", + "x-ms-client-name": "fileContentLanguage", + "in": "header", + "description": "Specifies the natural languages used by this resource.", + "required": false, + "type": "string", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "file-HTTP-headers" + } + }, + "FileContentMD5": { + "name": "x-ms-content-md5", + "x-ms-client-name": "fileContentMD5", + "in": "header", + "description": "Sets the file's MD5 hash.", + "required": false, + "type": "string", + "format": "byte", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "file-HTTP-headers" + } + }, + "FileContentType": { + "name": "x-ms-content-type", + "x-ms-client-name": "fileContentType", + "in": "header", + "description": "Sets the MIME content type of the file. The default type is 'application/octet-stream'.", + "required": false, + "type": "string", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "file-HTTP-headers" + } + }, + "FileType": { + "name": "x-ms-type", + "x-ms-client-name": "fileTypeConstant", + "in": "header", + "required": true, + "description": "Dummy constant parameter, file type can only be file.", + "type": "string", + "enum": [ + "file" + ], + "x-ms-parameter-location": "method" + }, + "GetRangeContentMD5": { + "name": "x-ms-range-get-content-md5", + "x-ms-client-name": "rangeGetContentMD5", + "in": "header", + "required": false, + "type": "boolean", + "x-ms-parameter-location": "method", + "description": "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." + }, + "HandleId": { + "name": "x-ms-handle-id", + "x-ms-client-name": "handleId", + "in": "header", + "description": "Specifies handle ID opened on the file or directory to be closed. Asterix (‘*’) is a wildcard that specifies all handles.", + "required": true, + "type": "string", + "x-ms-parameter-location": "method" + }, + "ListSharesInclude": { + "name": "include", + "in": "query", + "description": "Include this parameter to specify one or more datasets to include in the response.", + "required": false, + "type": "array", + "collectionFormat": "csv", + "items": { + "type": "string", + "enum": [ + "snapshots", + "metadata" + ], + "x-ms-enum": { + "name": "ListSharesIncludeType", + "modelAsString": false + } + }, + "x-ms-parameter-location": "method" + }, + "Marker": { + "name": "marker", + "in": "query", + "description": "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.", + "required": false, + "type": "string", + "x-ms-parameter-location": "method" + }, + "MaxResults": { + "name": "maxresults", + "in": "query", + "description": "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.", + "required": false, + "type": "integer", + "minimum": 1, + "x-ms-parameter-location": "method" + }, + "Metadata": { + "name": "x-ms-meta", + "x-ms-client-name": "metadata", + "in": "header", + "description": "A name-value pair to associate with a file storage object.", + "required": false, + "type": "string", + "x-ms-parameter-location": "method", + "x-ms-header-collection-prefix": "x-ms-meta-" + }, + "OptionalBody": { + "name": "optionalbody", + "in": "body", + "description": "Initial data.", + "required": false, + "schema": { + "type": "object", + "format": "file" + }, + "x-ms-parameter-location": "method" + }, + "Prefix": { + "name": "prefix", + "in": "query", + "description": "Filters the results to return only entries whose name begins with the specified prefix.", + "required": false, + "type": "string", + "x-ms-parameter-location": "method" + }, + "Range": { + "name": "x-ms-range", + "x-ms-client-name": "range", + "in": "header", + "description": "Return file data only from the specified byte range.", + "required": false, + "type": "string", + "x-ms-parameter-location": "method" + }, + "Recursive": { + "name": "x-ms-recursive", + "x-ms-client-name": "recursive", + "in": "header", + "description": "Specifies operation should apply to the directory specified in the URI, its files, its subdirectories and their files.", + "required": false, + "type": "boolean", + "x-ms-parameter-location": "method" + }, + "Url": { + "name": "url", + "in": "path", + "description": "The URL of the service account, share, directory or file that is the target of the desired operation.", + "required": true, + "type": "string", + "x-ms-skip-url-encoding": true + }, + "ShareAcl": { + "name": "shareAcl", + "in": "body", + "description": "The ACL for the share.", + "schema": { + "$ref": "#/definitions/SignedIdentifiers" + }, + "x-ms-parameter-location": "method" + }, + "ShareQuota": { + "name": "x-ms-share-quota", + "x-ms-client-name": "quota", + "in": "header", + "description": "Specifies the maximum size of the share, in gigabytes.", + "required": false, + "type": "integer", + "format": "int64", + "minimum": 1, + "x-ms-parameter-location": "method" + }, + "ShareSnapshot": { + "name": "sharesnapshot", + "in": "query", + "description": "The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query.", + "required": false, + "type": "string", + "x-ms-parameter-location": "method" + }, + "StorageServiceProperties": { + "name": "StorageServiceProperties", + "in": "body", + "description": "The StorageService properties.", + "required": true, + "schema": { + "$ref": "#/definitions/StorageServiceProperties" + }, + "x-ms-parameter-location": "method" + }, + "Timeout": { + "name": "timeout", + "in": "query", + "description": "The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations.", + "required": false, + "type": "integer", + "minimum": 0, + "x-ms-parameter-location": "method" + } + } +} \ No newline at end of file diff --git a/storage/client/queue/swagger/queue.json b/storage/client/queue/swagger/queue.json new file mode 100644 index 0000000000000..06155a07afed3 --- /dev/null +++ b/storage/client/queue/swagger/queue.json @@ -0,0 +1,1856 @@ +{ + "swagger": "2.0", + "info": { + "title": "Azure Queue Storage", + "version": "2018-03-28", + "x-ms-code-generation-settings": { + "header": "MIT", + "strictSpecAdherence": false + } + }, + "x-ms-parameterized-host": { + "hostTemplate": "{url}", + "useSchemePrefix": false, + "positionInOperation": "first", + "parameters": [ + { + "$ref": "#/parameters/Url" + } + ] + }, + "securityDefinitions": { + "queue_shared_key": { + "type": "apiKey", + "name": "Authorization", + "in": "header" + } + }, + "schemes": [ + "https" + ], + "consumes": [ + "application/xml" + ], + "produces": [ + "application/xml" + ], + "paths": {}, + "x-ms-paths": { + "/?restype=service&comp=properties": { + "put": { + "tags": [ + "service" + ], + "operationId": "Service_SetProperties", + "description": "Sets properties for a storage account's Queue service endpoint, including properties for Storage Analytics and CORS (Cross-Origin Resource Sharing) rules", + "parameters": [ + { + "$ref": "#/parameters/StorageServiceProperties" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "202": { + "description": "Success (Accepted)", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Queue service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "get": { + "tags": [ + "service" + ], + "operationId": "Service_GetProperties", + "description": "gets the properties of a storage account's Queue service, including properties for Storage Analytics and CORS (Cross-Origin Resource Sharing) rules.", + "parameters": [ + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "Success.", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Queue service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + } + }, + "schema": { + "$ref": "#/definitions/StorageServiceProperties" + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "restype", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "service" + ] + }, + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "properties" + ] + } + ] + }, + "/?restype=service&comp=stats": { + "get": { + "tags": [ + "service" + ], + "operationId": "Service_GetStatistics", + "description": "Retrieves statistics related to replication for the Queue service. It is only available on the secondary location endpoint when read-access geo-redundant replication is enabled for the storage account.", + "parameters": [ + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "Success.", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Queue service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + }, + "schema": { + "$ref": "#/definitions/StorageServiceStats" + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "restype", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "service" + ] + }, + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "stats" + ] + } + ] + }, + "/?comp=list": { + "get": { + "tags": [ + "service" + ], + "operationId": "Service_ListQueuesSegment", + "description": "The List Queues Segment operation returns a list of the queues under the specified account", + "parameters": [ + { + "$ref": "#/parameters/Prefix" + }, + { + "$ref": "#/parameters/Marker" + }, + { + "$ref": "#/parameters/MaxResults" + }, + { + "$ref": "#/parameters/ListQueuesInclude" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "Success.", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Queue service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + }, + "schema": { + "$ref": "#/definitions/ListQueuesSegmentResponse" + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "NextMarker" + } + }, + "parameters": [ + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "list" + ] + } + ] + }, + "/{queueName}": { + "put": { + "tags": [ + "service" + ], + "operationId": "Queue_Create", + "description": "creates a new queue under the given account.", + "parameters": [ + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/Metadata" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "201": { + "description": "Success, queue created.", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Queue service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + } + }, + "204": { + "description": "Success, queue created.", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Queue service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "delete": { + "tags": [ + "queue" + ], + "operationId": "Queue_Delete", + "description": "operation permanently deletes the specified queue", + "parameters": [ + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "204": { + "description": "No Content", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Queue service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [] + }, + "/{queueName}?comp=metadata": { + "get": { + "tags": [ + "queue" + ], + "operationId": "Queue_GetProperties", + "description": "Retrieves user-defined metadata and queue properties on the specified queue. Metadata is associated with the queue as name-values pairs.", + "parameters": [ + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "Success.", + "headers": { + "x-ms-meta": { + "type": "string", + "x-ms-client-name": "Metadata", + "x-ms-header-collection-prefix": "x-ms-meta-" + }, + "x-ms-approximate-messages-count": { + "type": "integer", + "x-ms-client-name": "ApproximateMessagesCount", + "description": "The approximate number of messages in the queue. This number is not lower than the actual number of messages in the queue, but could be higher." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Queue service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "put": { + "tags": [ + "queue" + ], + "operationId": "Queue_SetMetadata", + "description": "sets user-defined metadata on the specified queue. Metadata is associated with the queue as name-value pairs.", + "parameters": [ + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/Metadata" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "204": { + "description": "No Content", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Queue service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "metadata" + ] + } + ] + }, + "/{queueName}?comp=acl": { + "get": { + "tags": [ + "queue" + ], + "operationId": "Queue_GetAccessPolicy", + "description": "returns details about any stored access policies specified on the queue that may be used with Shared Access Signatures.", + "parameters": [ + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Queue service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + }, + "schema": { + "$ref": "#/definitions/SignedIdentifiers" + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "put": { + "tags": [ + "queue" + ], + "operationId": "Queue_SetAccessPolicy", + "description": "sets stored access policies for the queue that may be used with Shared Access Signatures", + "parameters": [ + { + "$ref": "#/parameters/QueueAcl" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "204": { + "description": "No Content", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Queue service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "acl" + ] + } + ] + }, + "/{queueName}/messages": { + "get": { + "tags": [ + "message" + ], + "operationId": "Messages_Dequeue", + "description": "The Dequeue operation retrieves one or more messages from the front of the queue.", + "parameters": [ + { + "$ref": "#/parameters/NumOfMessages" + }, + { + "$ref": "#/parameters/VisibilityTimeout" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "OK", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Queue service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + }, + "schema": { + "$ref": "#/definitions/DequeuedMessagesList" + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "delete": { + "tags": [ + "message" + ], + "operationId": "Messages_Clear", + "description": "The Clear operation deletes all messages from the specified queue.", + "parameters": [ + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "204": { + "description": "No Content", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Queue service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [] + }, + "/{queueName}/messages?visibilitytimeout={visibilityTimeout}&messagettl={messageTimeToLive}": { + "post": { + "tags": [ + "message" + ], + "operationId": "Messages_Enqueue", + "description": "The Enqueue operation adds a new message to the back of the message queue. A visibility timeout can also be specified to make the message invisible until the visibility timeout expires. A message must be in a format that can be included in an XML request with UTF-8 encoding. The encoded message can be up to 64 KB in size for versions 2011-08-18 and newer, or 8 KB in size for previous versions.", + "parameters": [ + { + "$ref": "#/parameters/QueueMessage" + }, + { + "$ref": "#/parameters/VisibilityTimeout" + }, + { + "$ref": "#/parameters/MessageTTL" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "201": { + "description": "Created", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Queue service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + }, + "schema": { + "$ref": "#/definitions/EnqueuedMessageList" + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [] + }, + "/{queueName}/messages?peekonly=true": { + "get": { + "tags": [ + "message" + ], + "operationId": "Messages_Peek", + "description": "The Peek operation retrieves one or more messages from the front of the queue, but does not alter the visibility of the message.", + "parameters": [ + { + "$ref": "#/parameters/NumOfMessages" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "OK", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Queue service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + }, + "schema": { + "$ref": "#/definitions/PeekedMessagesList" + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [ + { + "name": "peekonly", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "true" + ] + } + ] + }, + "/{queueName}/messages/{messageid}?popreceipt={popReceipt}&visibilitytimeout={visibilityTimeout}": { + "put": { + "tags": [ + "messageId" + ], + "operationId": "MessageId_Update", + "description": "The Update operation was introduced with version 2011-08-18 of the Queue service API. The Update Message operation updates the visibility timeout of a message. You can also use this operation to update the contents of a message. A message must be in a format that can be included in an XML request with UTF-8 encoding, and the encoded message can be up to 64KB in size.", + "parameters": [ + { + "$ref": "#/parameters/QueueMessage" + }, + { + "$ref": "#/parameters/PopReceipt" + }, + { + "$ref": "#/parameters/VisibilityTimeoutRequired" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "204": { + "description": "No Content", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Queue service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + }, + "x-ms-popreceipt": { + "x-ms-client-name": "PopReceipt", + "type": "string", + "description": "The pop receipt of the queue message." + }, + "x-ms-time-next-visible": { + "x-ms-client-name": "TimeNextVisible", + "type": "string", + "format": "date-time-rfc1123", + "description": "A UTC date/time value that represents when the message will be visible on the queue." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [] + }, + "/{queueName}/messages/{messageid}?popreceipt={popReceipt}": { + "delete": { + "tags": [ + "messageId" + ], + "operationId": "MessageId_Delete", + "description": "The Delete operation deletes the specified message.", + "parameters": [ + { + "$ref": "#/parameters/PopReceipt" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "204": { + "description": "No Content", + "headers": { + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Queue service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/StorageError" + } + } + } + }, + "parameters": [] + } + }, + "definitions": { + "AccessPolicy": { + "type": "object", + "required": [ + "Start", + "Expiry", + "Permission" + ], + "description": "An Access policy", + "properties": { + "Start": { + "description": "the date-time the policy is active", + "type": "string", + "format": "date-time" + }, + "Expiry": { + "description": "the date-time the policy expires", + "type": "string", + "format": "date-time" + }, + "Permission": { + "description": "the permissions for the acl policy", + "type": "string" + } + } + }, + "ListQueuesSegmentResponse": { + "xml": { + "name": "EnumerationResults" + }, + "description": "The object returned when calling List Queues on a Queue Service.", + "type": "object", + "required": [ + "ServiceEndpoint", + "Prefix", + "MaxResults", + "NextMarker" + ], + "properties": { + "ServiceEndpoint": { + "type": "string", + "xml": { + "attribute": true + } + }, + "Prefix": { + "type": "string" + }, + "Marker": { + "type": "string" + }, + "MaxResults": { + "type": "integer" + }, + "QueueItems": { + "xml": { + "wrapped": true, + "name": "Queues" + }, + "type": "array", + "items": { + "$ref": "#/definitions/QueueItem" + } + }, + "NextMarker": { + "type": "string" + } + } + }, + "CorsRule": { + "description": "CORS is an HTTP feature that enables a web application running under one domain to access resources in another domain. Web browsers implement a security restriction known as same-origin policy that prevents a web page from calling APIs in a different domain; CORS provides a secure way to allow one domain (the origin domain) to call APIs in another domain", + "type": "object", + "required": [ + "AllowedOrigins", + "AllowedMethods", + "AllowedHeaders", + "ExposedHeaders", + "MaxAgeInSeconds" + ], + "properties": { + "AllowedOrigins": { + "description": "The origin domains that are permitted to make a request against the storage service via CORS. The origin domain is the domain from which the request originates. Note that the origin must be an exact case-sensitive match with the origin that the user age sends to the service. You can also use the wildcard character '*' to allow all origin domains to make requests via CORS.", + "type": "string" + }, + "AllowedMethods": { + "description": "The methods (HTTP request verbs) that the origin domain may use for a CORS request. (comma separated)", + "type": "string" + }, + "AllowedHeaders": { + "description": "the request headers that the origin domain may specify on the CORS request.", + "type": "string" + }, + "ExposedHeaders": { + "description": "The response headers that may be sent in the response to the CORS request and exposed by the browser to the request issuer", + "type": "string" + }, + "MaxAgeInSeconds": { + "description": "The maximum amount time that a browser should cache the preflight OPTIONS request.", + "type": "integer", + "minimum": 0 + } + } + }, + "ErrorCode": { + "description": "Error codes returned by the service", + "type": "string", + "enum": [ + "AccountAlreadyExists", + "AccountBeingCreated", + "AccountIsDisabled", + "AuthenticationFailed", + "AuthorizationFailure", + "ConditionHeadersNotSupported", + "ConditionNotMet", + "EmptyMetadataKey", + "InsufficientAccountPermissions", + "InternalError", + "InvalidAuthenticationInfo", + "InvalidHeaderValue", + "InvalidHttpVerb", + "InvalidInput", + "InvalidMd5", + "InvalidMetadata", + "InvalidQueryParameterValue", + "InvalidRange", + "InvalidResourceName", + "InvalidUri", + "InvalidXmlDocument", + "InvalidXmlNodeValue", + "Md5Mismatch", + "MetadataTooLarge", + "MissingContentLengthHeader", + "MissingRequiredQueryParameter", + "MissingRequiredHeader", + "MissingRequiredXmlNode", + "MultipleConditionHeadersNotSupported", + "OperationTimedOut", + "OutOfRangeInput", + "OutOfRangeQueryParameterValue", + "RequestBodyTooLarge", + "ResourceTypeMismatch", + "RequestUrlFailedToParse", + "ResourceAlreadyExists", + "ResourceNotFound", + "ServerBusy", + "UnsupportedHeader", + "UnsupportedXmlNode", + "UnsupportedQueryParameter", + "UnsupportedHttpVerb", + "InvalidMarker", + "MessageNotFound", + "MessageTooLarge", + "PopReceiptMismatch", + "QueueAlreadyExists", + "QueueBeingDeleted", + "QueueDisabled", + "QueueNotEmpty", + "QueueNotFound" + ], + "x-ms-enum": { + "name": "StorageErrorCode", + "modelAsString": true + } + }, + "GeoReplication": { + "type": "object", + "required": [ + "Status", + "LastSyncTime" + ], + "properties": { + "Status": { + "description": "The status of the secondary location", + "type": "string", + "enum": [ + "live", + "bootstrap", + "unavailable" + ], + "x-ms-enum": { + "name": "GeoReplicationStatusType", + "modelAsString": true + } + }, + "LastSyncTime": { + "description": "A GMT date/time value, to the second. All primary writes preceding this value are guaranteed to be available for read operations at the secondary. Primary writes after this point in time may or may not be available for reads.", + "type": "string", + "format": "date-time-rfc1123" + } + } + }, + "Logging": { + "description": "Azure Analytics Logging settings.", + "type": "object", + "required": [ + "Version", + "Delete", + "Read", + "Write", + "RetentionPolicy" + ], + "properties": { + "Version": { + "description": "The version of Storage Analytics to configure.", + "type": "string" + }, + "Delete": { + "description": "Indicates whether all delete requests should be logged.", + "type": "boolean" + }, + "Read": { + "description": "Indicates whether all read requests should be logged.", + "type": "boolean" + }, + "Write": { + "description": "Indicates whether all write requests should be logged.", + "type": "boolean" + }, + "RetentionPolicy": { + "$ref": "#/definitions/RetentionPolicy" + } + } + }, + "Metadata": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "StorageError": { + "type": "object", + "properties": { + "Message": { + "type": "string" + } + } + }, + "Metrics": { + "description": "", + "required": [ + "Enabled" + ], + "properties": { + "Version": { + "description": "The version of Storage Analytics to configure.", + "type": "string" + }, + "Enabled": { + "description": "Indicates whether metrics are enabled for the Queue service.", + "type": "boolean" + }, + "IncludeAPIs": { + "description": "Indicates whether metrics should generate summary statistics for called API operations.", + "type": "boolean" + }, + "RetentionPolicy": { + "$ref": "#/definitions/RetentionPolicy" + } + } + }, + "QueueItem": { + "description": "An Azure Storage Queue.", + "type": "object", + "required": [ + "Name" + ], + "properties": { + "Name": { + "type": "string", + "description": "The name of the Queue." + }, + "Metadata": { + "$ref": "#/definitions/Metadata" + } + }, + "xml": { + "name": "Queue" + } + }, + "QueueMessage": { + "description": "A Message object which can be stored in a Queue", + "type": "object", + "required": [ + "MessageText" + ], + "properties": { + "MessageText": { + "type": "string", + "description": "The content of the message" + } + } + }, + "DequeuedMessage": { + "description": "The object returned in the QueueMessageList array when calling Get Messages on a Queue.", + "type": "object", + "required": [ + "MessageId", + "InsertionTime", + "ExpirationTime", + "PopReceipt", + "TimeNextVisible", + "DequeueCount", + "MessageText" + ], + "properties": { + "MessageId": { + "type": "string", + "description": "The Id of the Message." + }, + "InsertionTime": { + "type": "string", + "format": "date-time-rfc1123", + "description": "The time the Message was inserted into the Queue." + }, + "ExpirationTime": { + "type": "string", + "format": "date-time-rfc1123", + "description": "The time that the Message will expire and be automatically deleted." + }, + "PopReceipt": { + "type": "string", + "description": "This value is required to delete the Message. If deletion fails using this popreceipt then the message has been dequeued by another client." + }, + "TimeNextVisible": { + "type": "string", + "format": "date-time-rfc1123", + "description": "The time that the message will again become visible in the Queue." + }, + "DequeueCount": { + "type": "integer", + "format": "int64", + "description": "The number of times the message has been dequeued." + }, + "MessageText": { + "type": "string", + "description": "The content of the Message." + } + }, + "xml": { + "wrapped": true, + "name": "QueueMessage" + } + }, + "PeekedMessageItem": { + "description": "The object returned in the QueueMessageList array when calling Peek Messages on a Queue", + "type": "object", + "required": [ + "MessageId", + "InsertionTime", + "ExpirationTime", + "DequeueCount", + "MessageText" + ], + "properties": { + "MessageId": { + "type": "string", + "description": "The Id of the Message." + }, + "InsertionTime": { + "type": "string", + "format": "date-time-rfc1123", + "description": "The time the Message was inserted into the Queue." + }, + "ExpirationTime": { + "type": "string", + "format": "date-time-rfc1123", + "description": "The time that the Message will expire and be automatically deleted." + }, + "DequeueCount": { + "type": "integer", + "format": "int64", + "description": "The number of times the message has been dequeued." + }, + "MessageText": { + "type": "string", + "description": "The content of the Message." + } + }, + "xml": { + "wrapped": true, + "name": "QueueMessage" + } + }, + "EnqueuedMessage": { + "description": "The object returned in the QueueMessageList array when calling Put Message on a Queue", + "type": "object", + "required": [ + "MessageId", + "InsertionTime", + "ExpirationTime", + "PopReceipt", + "TimeNextVisible" + ], + "properties": { + "MessageId": { + "type": "string", + "description": "The Id of the Message." + }, + "InsertionTime": { + "type": "string", + "format": "date-time-rfc1123", + "description": "The time the Message was inserted into the Queue." + }, + "ExpirationTime": { + "type": "string", + "format": "date-time-rfc1123", + "description": "The time that the Message will expire and be automatically deleted." + }, + "PopReceipt": { + "type": "string", + "description": "This value is required to delete the Message. If deletion fails using this popreceipt then the message has been dequeued by another client." + }, + "TimeNextVisible": { + "type": "string", + "format": "date-time-rfc1123", + "description": "The time that the message will again become visible in the Queue." + } + }, + "xml": { + "wrapped": true, + "name": "QueueMessage" + } + }, + "DequeuedMessagesList": { + "description": "The object returned when calling Get Messages on a Queue", + "type": "array", + "items": { + "$ref": "#/definitions/DequeuedMessage", + "xml": { + "name": "QueueMessage" + } + }, + "xml": { + "wrapped": true, + "name": "QueueMessagesList" + } + }, + "PeekedMessagesList": { + "description": "The object returned when calling Peek Messages on a Queue", + "type": "array", + "items": { + "$ref": "#/definitions/PeekedMessageItem", + "xml": { + "name": "QueueMessage" + } + }, + "xml": { + "wrapped": true, + "name": "QueueMessagesList" + } + }, + "EnqueuedMessageList": { + "description": "The object returned when calling Put Message on a Queue", + "type": "array", + "items": { + "$ref": "#/definitions/EnqueuedMessage", + "xml": { + "name": "QueueMessage" + } + }, + "xml": { + "wrapped": true, + "name": "QueueMessagesList" + } + }, + "RetentionPolicy": { + "description": "the retention policy", + "type": "object", + "required": [ + "Enabled" + ], + "properties": { + "Enabled": { + "description": "Indicates whether a retention policy is enabled for the storage service", + "type": "boolean" + }, + "Days": { + "description": "Indicates the number of days that metrics or logging or soft-deleted data should be retained. All data older than this value will be deleted", + "type": "integer", + "minimum": 1 + } + } + }, + "SignedIdentifier": { + "description": "signed identifier", + "type": "object", + "required": [ + "Id", + "AccessPolicy" + ], + "properties": { + "Id": { + "type": "string", + "description": "a unique id" + }, + "AccessPolicy": { + "description": "The access policy", + "$ref": "#/definitions/AccessPolicy" + } + } + }, + "SignedIdentifiers": { + "description": "a collection of signed identifiers", + "type": "array", + "items": { + "$ref": "#/definitions/SignedIdentifier", + "xml": { + "name": "SignedIdentifier" + } + }, + "xml": { + "wrapped": true, + "name": "SignedIdentifiers" + } + }, + "StorageServiceProperties": { + "description": "Storage Service Properties.", + "type": "object", + "properties": { + "Logging": { + "description": "Azure Analytics Logging settings", + "$ref": "#/definitions/Logging" + }, + "HourMetrics": { + "description": "A summary of request statistics grouped by API in hourly aggregates for queues", + "$ref": "#/definitions/Metrics" + }, + "MinuteMetrics": { + "description": "a summary of request statistics grouped by API in minute aggregates for queues", + "$ref": "#/definitions/Metrics" + }, + "Cors": { + "description": "The set of CORS rules.", + "type": "array", + "items": { + "$ref": "#/definitions/CorsRule", + "xml": { + "name": "CorsRule" + } + }, + "xml": { + "wrapped": true + } + } + } + }, + "StorageServiceStats": { + "description": "Stats for the storage service.", + "type": "object", + "properties": { + "GeoReplication": { + "description": "Geo-Replication information for the Secondary Storage Service", + "$ref": "#/definitions/GeoReplication" + } + } + } + }, + "parameters": { + "Url": { + "name": "url", + "description": "The URL of the service account, queue or message that is the targe of the desired operation.", + "required": true, + "type": "string", + "in": "path", + "x-ms-skip-url-encoding": true + }, + "ApiVersionParameter": { + "name": "x-ms-version", + "x-ms-client-name": "version", + "in": "header", + "required": true, + "type": "string", + "description": "Specifies the version of the operation to use for this request.", + "enum": [ + "2018-03-28" + ] + }, + "Body": { + "name": "body", + "in": "body", + "required": true, + "schema": { + "type": "object", + "format": "file" + }, + "x-ms-parameter-location": "method", + "description": "Initial data" + }, + "QueueAcl": { + "name": "queueAcl", + "in": "body", + "schema": { + "$ref": "#/definitions/SignedIdentifiers" + }, + "x-ms-parameter-location": "method", + "description": "the acls for the queue" + }, + "ClientRequestId": { + "name": "x-ms-client-request-id", + "x-ms-client-name": "requestId", + "in": "header", + "required": false, + "type": "string", + "x-ms-parameter-location": "method", + "description": "Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage analytics logging is enabled." + }, + "ContentLength": { + "name": "Content-Length", + "in": "header", + "required": true, + "type": "integer", + "format": "int64", + "x-ms-parameter-location": "method", + "description": "The length of the request." + }, + "ListQueuesInclude": { + "name": "include", + "in": "query", + "required": false, + "type": "array", + "collectionFormat": "csv", + "items": { + "type": "string", + "enum": [ + "metadata" + ], + "x-ms-enum": { + "name": "ListQueuesIncludeType", + "modelAsString": false + } + }, + "x-ms-parameter-location": "method", + "description": "Include this parameter to specify that the queues's metadata be returned as part of the response body." + }, + "Marker": { + "name": "marker", + "in": "query", + "required": false, + "type": "string", + "description": "A string value that identifies the portion of the list of queues to be returned with the next listing operation. The operation returns the NextMarker value within the response body if the listing operation did not return all queues remaining to be listed with the current page. The NextMarker value can be used as the value for the marker parameter in a subsequent call to request the next page of list items. The marker value is opaque to the client.", + "x-ms-parameter-location": "method" + }, + "MaxResults": { + "name": "maxresults", + "in": "query", + "required": false, + "type": "integer", + "minimum": 1, + "x-ms-parameter-location": "method", + "description": "Specifies the maximum number of queues to return. If the request does not specify maxresults, or specifies a value greater than 5000, the server will return up to 5000 items. Note that if the listing operation crosses a partition boundary, then the service will return a continuation token for retrieving the remainder of the results. For this reason, it is possible that the service will return fewer results than specified by maxresults, or than the default of 5000." + }, + "MessageId": { + "name": "messageid", + "in": "path", + "required": true, + "type": "string", + "x-ms-parameter-location": "method", + "description": "The container name." + }, + "MessageTTL": { + "name": "messagettl", + "x-ms-client-name": "MessageTimeToLive", + "in": "query", + "required": false, + "type": "integer", + "minimum": -1, + "x-ms-parameter-location": "method", + "description": "Optional. Specifies the time-to-live interval for the message, in seconds. Prior to version 2017-07-29, the maximum time-to-live allowed is 7 days. For version 2017-07-29 or later, the maximum time-to-live can be any positive number, as well as -1 indicating that the message does not expire. If this parameter is omitted, the default time-to-live is 7 days." + }, + "Metadata": { + "name": "x-ms-meta", + "x-ms-client-name": "metadata", + "in": "header", + "required": false, + "type": "string", + "x-ms-parameter-location": "method", + "description": "Optional. Include this parameter to specify that the queue's metadata be returned as part of the response body. Note that metadata requested with this parameter must be stored in accordance with the naming restrictions imposed by the 2009-09-19 version of the Queue service. Beginning with this version, all metadata names must adhere to the naming conventions for C# identifiers.", + "x-ms-header-collection-prefix": "x-ms-meta-" + }, + "NumOfMessages": { + "name": "numofmessages", + "x-ms-client-name": "numberOfMessages", + "in": "query", + "required": false, + "type": "integer", + "minimum": 1, + "x-ms-parameter-location": "method", + "description": "Optional. A nonzero integer value that specifies the number of messages to retrieve from the queue, up to a maximum of 32. If fewer are visible, the visible messages are returned. By default, a single message is retrieved from the queue with this operation." + }, + "PopReceipt": { + "name": "popreceipt", + "x-ms-client-name": "popReceipt", + "in": "query", + "required": true, + "x-ms-parameter-location": "method", + "description": "Required. Specifies the valid pop receipt value returned from an earlier call to the Get Messages or Update Message operation.", + "type": "string" + }, + "Prefix": { + "name": "prefix", + "in": "query", + "required": false, + "type": "string", + "description": "Filters the results to return only queues whose name begins with the specified prefix.", + "x-ms-parameter-location": "method" + }, + "QueueMessage": { + "name": "QueueMessage", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/QueueMessage" + }, + "x-ms-parameter-location": "method", + "description": "A Message object which can be stored in a Queue" + }, + "QueueName": { + "name": "queueName", + "in": "path", + "required": true, + "type": "string", + "x-ms-parameter-location": "method", + "description": "The queue name." + }, + "StorageServiceProperties": { + "name": "StorageServiceProperties", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/StorageServiceProperties" + }, + "x-ms-parameter-location": "method", + "description": "The StorageService properties." + }, + "Timeout": { + "name": "timeout", + "in": "query", + "required": false, + "type": "integer", + "minimum": 0, + "x-ms-parameter-location": "method", + "description": "The The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Queue Service Operations." + }, + "VisibilityTimeout": { + "name": "visibilitytimeout", + "in": "query", + "required": false, + "type": "integer", + "minimum": 0, + "maximum": 604800, + "x-ms-parameter-location": "method", + "description": "Optional. Specifies the new visibility timeout value, in seconds, relative to server time. The default value is 30 seconds. A specified value must be larger than or equal to 1 second, and cannot be larger than 7 days, or larger than 2 hours on REST protocol versions prior to version 2011-08-18. The visibility timeout of a message can be set to a value later than the expiry time." + }, + "VisibilityTimeoutRequired": { + "name": "visibilitytimeout", + "in": "query", + "required": true, + "type": "integer", + "minimum": 0, + "maximum": 604800, + "x-ms-parameter-location": "method", + "description": "Optional. Specifies the new visibility timeout value, in seconds, relative to server time. The default value is 30 seconds. A specified value must be larger than or equal to 1 second, and cannot be larger than 7 days, or larger than 2 hours on REST protocol versions prior to version 2011-08-18. The visibility timeout of a message can be set to a value later than the expiry time." + } + } +} \ No newline at end of file From 593ebf2d056dd6096dd2a56307a8711a581c1c93 Mon Sep 17 00:00:00 2001 From: Jianghao Lu Date: Thu, 18 Jul 2019 18:27:15 -0700 Subject: [PATCH 04/17] Update Storage to azure-core preview 3 --- storage/client/blob/pom.xml | 4 +- .../blob/implementation/AppendBlobsImpl.java | 40 +-- .../AzureBlobStorageBuilder.java | 2 + .../implementation/AzureBlobStorageImpl.java | 19 +- .../blob/implementation/BlobsImpl.java | 105 +++++--- .../blob/implementation/BlockBlobsImpl.java | 55 ++-- .../blob/implementation/ContainersImpl.java | 85 ++++--- .../blob/implementation/PageBlobsImpl.java | 75 +++--- .../blob/implementation/ServicesImpl.java | 51 ++-- .../SignedIdentifiersWrapper.java | 2 +- .../storage/blob/models/AccessPolicy.java | 2 + .../AppendBlobAppendBlockFromUrlHeaders.java | 2 + .../models/AppendBlobAppendBlockHeaders.java | 2 + .../blob/models/AppendBlobCreateHeaders.java | 2 + .../AppendPositionAccessConditions.java | 2 + .../models/BlobAbortCopyFromURLHeaders.java | 2 + .../blob/models/BlobAcquireLeaseHeaders.java | 2 + .../blob/models/BlobBreakLeaseHeaders.java | 2 + .../blob/models/BlobChangeLeaseHeaders.java | 2 + .../blob/models/BlobCopyFromURLHeaders.java | 2 + .../models/BlobCreateSnapshotHeaders.java | 2 + .../blob/models/BlobDeleteHeaders.java | 2 + .../blob/models/BlobDownloadHeaders.java | 4 +- .../blob/models/BlobFlatListSegment.java | 2 + .../models/BlobGetAccountInfoHeaders.java | 2 + .../blob/models/BlobGetPropertiesHeaders.java | 4 +- .../storage/blob/models/BlobHTTPHeaders.java | 2 + .../blob/models/BlobHierarchyListSegment.java | 4 +- .../storage/blob/models/BlobMetadata.java | 2 + .../azure/storage/blob/models/BlobPrefix.java | 2 + .../storage/blob/models/BlobProperties.java | 2 + .../blob/models/BlobReleaseLeaseHeaders.java | 2 + .../blob/models/BlobRenewLeaseHeaders.java | 2 + .../models/BlobSetHTTPHeadersHeaders.java | 2 + .../blob/models/BlobSetMetadataHeaders.java | 2 + .../blob/models/BlobSetTierHeaders.java | 2 + .../models/BlobStartCopyFromURLHeaders.java | 2 + .../blob/models/BlobUndeleteHeaders.java | 2 + .../com/azure/storage/blob/models/Block.java | 2 + .../BlockBlobCommitBlockListHeaders.java | 2 + .../models/BlockBlobGetBlockListHeaders.java | 2 + .../BlockBlobStageBlockFromURLHeaders.java | 2 + .../models/BlockBlobStageBlockHeaders.java | 2 + .../blob/models/BlockBlobUploadHeaders.java | 2 + .../azure/storage/blob/models/BlockList.java | 2 + .../storage/blob/models/BlockLookupList.java | 2 + .../azure/storage/blob/models/ClearRange.java | 2 + .../models/ContainerAcquireLeaseHeaders.java | 2 + .../models/ContainerBreakLeaseHeaders.java | 2 + .../models/ContainerChangeLeaseHeaders.java | 2 + .../blob/models/ContainerCreateHeaders.java | 2 + .../blob/models/ContainerDeleteHeaders.java | 2 + .../ContainerGetAccessPolicyHeaders.java | 2 + .../ContainerGetAccountInfoHeaders.java | 2 + .../models/ContainerGetPropertiesHeaders.java | 4 +- .../storage/blob/models/ContainerItem.java | 2 + .../ContainerListBlobFlatSegmentHeaders.java | 2 + ...tainerListBlobHierarchySegmentHeaders.java | 2 + .../blob/models/ContainerProperties.java | 2 + .../models/ContainerReleaseLeaseHeaders.java | 2 + .../models/ContainerRenewLeaseHeaders.java | 2 + .../ContainerSetAccessPolicyHeaders.java | 2 + .../models/ContainerSetMetadataHeaders.java | 2 + .../azure/storage/blob/models/CorsRule.java | 2 + .../storage/blob/models/GeoReplication.java | 2 + .../azure/storage/blob/models/KeyInfo.java | 2 + .../blob/models/LeaseAccessConditions.java | 2 + .../models/ListBlobsFlatSegmentResponse.java | 2 + .../ListBlobsHierarchySegmentResponse.java | 2 + .../models/ListContainersSegmentResponse.java | 2 + .../azure/storage/blob/models/Logging.java | 2 + .../azure/storage/blob/models/Metrics.java | 2 + .../blob/models/ModifiedAccessConditions.java | 2 + .../models/PageBlobClearPagesHeaders.java | 2 + .../PageBlobCopyIncrementalHeaders.java | 2 + .../blob/models/PageBlobCreateHeaders.java | 2 + .../PageBlobGetPageRangesDiffHeaders.java | 2 + .../models/PageBlobGetPageRangesHeaders.java | 2 + .../blob/models/PageBlobResizeHeaders.java | 2 + .../PageBlobUpdateSequenceNumberHeaders.java | 2 + .../PageBlobUploadPagesFromURLHeaders.java | 2 + .../models/PageBlobUploadPagesHeaders.java | 2 + .../azure/storage/blob/models/PageList.java | 2 + .../azure/storage/blob/models/PageRange.java | 2 + .../storage/blob/models/RetentionPolicy.java | 2 + .../SequenceNumberAccessConditions.java | 2 + .../models/ServiceGetAccountInfoHeaders.java | 2 + .../models/ServiceGetPropertiesHeaders.java | 2 + .../models/ServiceGetStatisticsHeaders.java | 2 + .../ServiceGetUserDelegationKeyHeaders.java | 2 + .../ServiceListContainersSegmentHeaders.java | 2 + .../models/ServiceSetPropertiesHeaders.java | 2 + .../storage/blob/models/SignedIdentifier.java | 2 + .../SourceModifiedAccessConditions.java | 2 + .../storage/blob/models/StaticWebsite.java | 2 + .../storage/blob/models/StorageError.java | 2 + .../blob/models/StorageServiceProperties.java | 2 + .../blob/models/StorageServiceStats.java | 2 + .../blob/models/UserDelegationKey.java | 2 + .../storage/blob/models/package-info.java | 2 +- .../AzureFileStorageBuilder.java | 4 +- .../implementation/AzureFileStorageImpl.java | 19 +- .../file/implementation/DirectorysImpl.java | 57 +++-- .../file/implementation/FilesImpl.java | 81 +++--- .../file/implementation/ServicesImpl.java | 41 +-- .../file/implementation/SharesImpl.java | 79 +++--- .../storage/file/models/AccessPolicy.java | 2 + .../azure/storage/file/models/CorsRule.java | 2 + .../models/DeleteSnapshotsOptionType.java | 7 +- .../file/models/DirectoryCreateHeaders.java | 2 + .../file/models/DirectoryDeleteHeaders.java | 2 + .../DirectoryForceCloseHandlesHeaders.java | 2 + .../models/DirectoryGetPropertiesHeaders.java | 4 +- .../storage/file/models/DirectoryItem.java | 2 + ...ListFilesAndDirectoriesSegmentHeaders.java | 2 + .../models/DirectoryListHandlesHeaders.java | 2 + .../models/DirectorySetMetadataHeaders.java | 2 + .../file/models/FileAbortCopyHeaders.java | 2 + .../file/models/FileCreateHeaders.java | 2 + .../file/models/FileDeleteHeaders.java | 2 + .../file/models/FileDownloadHeaders.java | 14 +- .../models/FileForceCloseHandlesHeaders.java | 2 + .../file/models/FileGetPropertiesHeaders.java | 10 +- .../file/models/FileGetRangeListHeaders.java | 2 + .../storage/file/models/FileHTTPHeaders.java | 8 +- .../azure/storage/file/models/FileItem.java | 2 + .../file/models/FileListHandlesHeaders.java | 2 + .../storage/file/models/FileProperty.java | 2 + .../models/FileSetHTTPHeadersHeaders.java | 2 + .../file/models/FileSetMetadataHeaders.java | 2 + .../file/models/FileStartCopyHeaders.java | 2 + .../file/models/FileUploadRangeHeaders.java | 8 +- .../FilesAndDirectoriesListSegment.java | 2 + .../azure/storage/file/models/HandleItem.java | 2 + ...istFilesAndDirectoriesSegmentResponse.java | 2 + .../file/models/ListHandlesResponse.java | 2 + .../file/models/ListSharesResponse.java | 2 + .../azure/storage/file/models/Metrics.java | 2 + .../com/azure/storage/file/models/Range.java | 2 + .../storage/file/models/RetentionPolicy.java | 2 + .../models/ServiceGetPropertiesHeaders.java | 2 + .../ServiceListSharesSegmentHeaders.java | 2 + .../models/ServiceSetPropertiesHeaders.java | 2 + .../file/models/ShareCreateHeaders.java | 2 + .../models/ShareCreateSnapshotHeaders.java | 2 + .../file/models/ShareDeleteHeaders.java | 2 + .../models/ShareGetAccessPolicyHeaders.java | 2 + .../models/ShareGetPropertiesHeaders.java | 10 +- .../models/ShareGetStatisticsHeaders.java | 2 + .../azure/storage/file/models/ShareItem.java | 2 + .../storage/file/models/ShareProperties.java | 8 +- .../models/ShareSetAccessPolicyHeaders.java | 2 + .../file/models/ShareSetMetadataHeaders.java | 2 + .../file/models/ShareSetQuotaHeaders.java | 2 + .../azure/storage/file/models/ShareStats.java | 2 + .../storage/file/models/SignedIdentifier.java | 2 + .../storage/file/models/StorageError.java | 2 + .../file/models/StorageServiceProperties.java | 2 + .../AzureQueueStorageBuilder.java | 4 +- .../implementation/AzureQueueStorageImpl.java | 19 +- .../queue/implementation/MessageIdsImpl.java | 34 +-- .../queue/implementation/MessagesImpl.java | 44 ++-- .../queue/implementation/QueuesImpl.java | 55 ++-- .../queue/implementation/ServicesImpl.java | 45 ++-- .../storage/queue/models/AccessPolicy.java | 2 + .../azure/storage/queue/models/CorsRule.java | 2 + .../storage/queue/models/DequeuedMessage.java | 235 ++++++++++++++++++ .../storage/queue/models/EnqueuedMessage.java | 2 + .../storage/queue/models/GeoReplication.java | 2 + .../models/ListQueuesSegmentResponse.java | 2 + .../azure/storage/queue/models/Logging.java | 2 + .../queue/models/MessageIdDeleteHeaders.java | 2 + .../queue/models/MessageIdUpdateHeaders.java | 2 + .../queue/models/MessagesClearHeaders.java | 2 + .../queue/models/MessagesDequeueHeaders.java | 2 + .../queue/models/MessagesDequeueResponse.java | 6 +- .../queue/models/MessagesEnqueueHeaders.java | 2 + .../queue/models/MessagesPeekHeaders.java | 2 + .../azure/storage/queue/models/Metrics.java | 2 + .../queue/models/PeekedMessageItem.java | 2 + .../queue/models/QueueCreateHeaders.java | 2 + .../queue/models/QueueDeleteHeaders.java | 2 + .../models/QueueGetAccessPolicyHeaders.java | 2 + .../models/QueueGetPropertiesHeaders.java | 4 +- .../azure/storage/queue/models/QueueItem.java | 2 + .../storage/queue/models/QueueMessage.java | 2 + .../models/QueueSetAccessPolicyHeaders.java | 2 + .../queue/models/QueueSetMetadataHeaders.java | 2 + .../storage/queue/models/RetentionPolicy.java | 2 + .../models/ServiceGetPropertiesHeaders.java | 2 + .../models/ServiceGetStatisticsHeaders.java | 2 + .../ServiceListQueuesSegmentHeaders.java | 2 + .../models/ServiceSetPropertiesHeaders.java | 2 + .../queue/models/SignedIdentifier.java | 2 + .../storage/queue/models/StorageError.java | 2 + .../models/StorageServiceProperties.java | 2 + .../queue/models/StorageServiceStats.java | 2 + 197 files changed, 1202 insertions(+), 368 deletions(-) create mode 100644 storage/client/queue/src/main/java/com/azure/storage/queue/models/DequeuedMessage.java diff --git a/storage/client/blob/pom.xml b/storage/client/blob/pom.xml index b661ff0ad7e2d..00132d720cd8c 100644 --- a/storage/client/blob/pom.xml +++ b/storage/client/blob/pom.xml @@ -49,7 +49,7 @@ com.azure azure-core - 1.0.0-preview.2 + 1.0.0-preview.3 org.slf4j @@ -69,7 +69,7 @@ com.azure azure-core-test - 1.0.0-preview.2 + 1.0.0-preview.3 test diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/AppendBlobsImpl.java b/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/AppendBlobsImpl.java index a6f486ff075f7..2763bb76a36d3 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/AppendBlobsImpl.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/AppendBlobsImpl.java @@ -4,18 +4,20 @@ package com.azure.storage.blob.implementation; -import com.azure.core.annotations.BodyParam; -import com.azure.core.annotations.ExpectedResponses; -import com.azure.core.annotations.HeaderParam; -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; import com.azure.core.implementation.DateTimeRfc1123; import com.azure.core.implementation.RestProxy; +import com.azure.core.implementation.annotation.BodyParam; +import com.azure.core.implementation.annotation.ExpectedResponses; +import com.azure.core.implementation.annotation.HeaderParam; +import com.azure.core.implementation.annotation.Host; +import com.azure.core.implementation.annotation.HostParam; +import com.azure.core.implementation.annotation.PathParam; +import com.azure.core.implementation.annotation.Put; +import com.azure.core.implementation.annotation.QueryParam; +import com.azure.core.implementation.annotation.ReturnType; +import com.azure.core.implementation.annotation.ServiceInterface; +import com.azure.core.implementation.annotation.ServiceMethod; +import com.azure.core.implementation.annotation.UnexpectedResponseExceptionType; import com.azure.core.implementation.util.Base64Util; import com.azure.core.util.Context; import com.azure.storage.blob.models.AppendBlobsAppendBlockFromUrlResponse; @@ -56,7 +58,7 @@ public final class AppendBlobsImpl { * @param client the instance of the service client containing this operation class. */ public AppendBlobsImpl(AzureBlobStorageImpl client) { - this.service = RestProxy.create(AppendBlobsService.class, client); + this.service = RestProxy.create(AppendBlobsService.class, client.httpPipeline()); this.client = client; } @@ -65,20 +67,20 @@ public AppendBlobsImpl(AzureBlobStorageImpl client) { * the proxy service to perform REST calls. */ @Host("{url}") - @Service("Storage Blobs AppendBlob") + @ServiceInterface(name = "AppendBlobs") private interface AppendBlobsService { - @PUT("{containerName}/{blob}") + @Put("{containerName}/{blob}") @ExpectedResponses({201}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono create(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("Content-Length") long contentLength, @HeaderParam("x-ms-meta-") Map metadata, @QueryParam("x-ms-encryption-key") String encryptionKey, @QueryParam("x-ms-encryption-key-sha256") String encryptionKeySha256, @QueryParam("x-ms-encryption-algorithm") EncryptionAlgorithmType encryptionAlgorithm, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @HeaderParam("x-ms-blob-type") String blobType, @HeaderParam("x-ms-blob-content-type") String blobContentType, @HeaderParam("x-ms-blob-content-encoding") String blobContentEncoding, @HeaderParam("x-ms-blob-content-language") String blobContentLanguage, @HeaderParam("x-ms-blob-content-md5") String blobContentMD5, @HeaderParam("x-ms-blob-cache-control") String blobCacheControl, @HeaderParam("x-ms-blob-content-disposition") String blobContentDisposition, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, Context context); - @PUT("{containerName}/{blob}") + @Put("{containerName}/{blob}") @ExpectedResponses({201}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono appendBlock(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @BodyParam("application/octet-stream") Flux body, @QueryParam("timeout") Integer timeout, @HeaderParam("Content-Length") long contentLength, @HeaderParam("Content-MD5") String transactionalContentMD5, @QueryParam("x-ms-encryption-key") String encryptionKey, @QueryParam("x-ms-encryption-key-sha256") String encryptionKeySha256, @QueryParam("x-ms-encryption-algorithm") EncryptionAlgorithmType encryptionAlgorithm, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("x-ms-blob-condition-maxsize") Long maxSize, @HeaderParam("x-ms-blob-condition-appendpos") Long appendPosition, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, Context context); - @PUT("{containerName}/{blob}") - @ExpectedResponses({201}) + @Put("{containerName}/{blob}") + @ExpectedResponses({201, 304}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono appendBlockFromUrl(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @HeaderParam("x-ms-copy-source") URL copySource, @HeaderParam("x-ms-source-range") String sourceRange, @HeaderParam("x-ms-source-content-md5") String sourceContentMD5, @QueryParam("timeout") Integer timeout, @HeaderParam("Content-Length") long contentLength, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("x-ms-blob-condition-maxsize") Long maxSize, @HeaderParam("x-ms-blob-condition-appendpos") Long appendPosition, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, @HeaderParam("x-ms-source-if-modified-since") DateTimeRfc1123 sourceIfModifiedSince, @HeaderParam("x-ms-source-if-unmodified-since") DateTimeRfc1123 sourceIfUnmodifiedSince, @HeaderParam("x-ms-source-if-match") String sourceIfMatch, @HeaderParam("x-ms-source-if-none-match") String sourceIfNoneMatch, Context context); } @@ -93,6 +95,7 @@ private interface AppendBlobsService { * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono createWithRestResponseAsync(String containerName, String blob, long contentLength, Context context) { final Integer timeout = null; final Map metadata = null; @@ -134,6 +137,7 @@ public Mono createWithRestResponseAsync(String contai * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono createWithRestResponseAsync(String containerName, String blob, long contentLength, Integer timeout, Map metadata, String encryptionKey, String encryptionKeySha256, EncryptionAlgorithmType encryptionAlgorithm, String requestId, BlobHTTPHeaders blobHTTPHeaders, LeaseAccessConditions leaseAccessConditions, ModifiedAccessConditions modifiedAccessConditions, Context context) { final String blobType = "AppendBlob"; String blobContentType = null; @@ -197,6 +201,7 @@ public Mono createWithRestResponseAsync(String contai * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono appendBlockWithRestResponseAsync(String containerName, String blob, Flux body, long contentLength, Context context) { final Integer timeout = null; final String encryptionKey = null; @@ -235,6 +240,7 @@ public Mono appendBlockWithRestResponseAsync(Str * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono appendBlockWithRestResponseAsync(String containerName, String blob, Flux body, long contentLength, Integer timeout, byte[] transactionalContentMD5, String encryptionKey, String encryptionKeySha256, EncryptionAlgorithmType encryptionAlgorithm, String requestId, LeaseAccessConditions leaseAccessConditions, AppendPositionAccessConditions appendPositionAccessConditions, ModifiedAccessConditions modifiedAccessConditions, Context context) { final String comp = "appendblock"; String leaseId = null; @@ -282,6 +288,7 @@ public Mono appendBlockWithRestResponseAsync(Str * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono appendBlockFromUrlWithRestResponseAsync(String containerName, String blob, URL sourceUrl, long contentLength, Context context) { final String sourceRange = null; final Integer timeout = null; @@ -321,6 +328,7 @@ public Mono appendBlockFromUrlWithRestRes * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono appendBlockFromUrlWithRestResponseAsync(String containerName, String blob, URL sourceUrl, long contentLength, String sourceRange, byte[] sourceContentMD5, Integer timeout, String requestId, LeaseAccessConditions leaseAccessConditions, AppendPositionAccessConditions appendPositionAccessConditions, ModifiedAccessConditions modifiedAccessConditions, SourceModifiedAccessConditions sourceModifiedAccessConditions, Context context) { final String comp = "appendblock"; String leaseId = null; diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/AzureBlobStorageBuilder.java b/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/AzureBlobStorageBuilder.java index c77d984c4e928..5a9ae355966ed 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/AzureBlobStorageBuilder.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/AzureBlobStorageBuilder.java @@ -6,10 +6,12 @@ import com.azure.core.http.HttpPipeline; import com.azure.core.implementation.RestProxy; +import com.azure.core.implementation.annotation.ServiceClientBuilder; /** * A builder for creating a new instance of the AzureBlobStorage type. */ +@ServiceClientBuilder(serviceClients = AzureBlobStorageImpl.class) public final class AzureBlobStorageBuilder { /* * The URL of the service account, container, or blob that is the targe of the desired operation. diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/AzureBlobStorageImpl.java b/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/AzureBlobStorageImpl.java index 6702b82da14ea..dd6f2da500b20 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/AzureBlobStorageImpl.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/AzureBlobStorageImpl.java @@ -4,14 +4,13 @@ package com.azure.storage.blob.implementation; -import com.azure.core.ServiceClient; import com.azure.core.http.HttpPipeline; import com.azure.core.implementation.RestProxy; /** * Initializes a new instance of the AzureBlobStorage type. */ -public final class AzureBlobStorageImpl extends ServiceClient { +public final class AzureBlobStorageImpl { /** * The URL of the service account, container, or blob that is the targe of the desired operation. */ @@ -62,6 +61,20 @@ AzureBlobStorageImpl version(String version) { return this; } + /** + * The HTTP pipeline to send requests through. + */ + private HttpPipeline httpPipeline; + + /** + * Gets The HTTP pipeline to send requests through. + * + * @return the httpPipeline value. + */ + public HttpPipeline httpPipeline() { + return this.httpPipeline; + } + /** * The ServicesImpl object to access its operations. */ @@ -159,7 +172,7 @@ public AzureBlobStorageImpl() { * @param httpPipeline The HTTP pipeline to send requests through. */ public AzureBlobStorageImpl(HttpPipeline httpPipeline) { - super(httpPipeline); + this.httpPipeline = httpPipeline; this.services = new ServicesImpl(this); this.containers = new ContainersImpl(this); this.blobs = new BlobsImpl(this); diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/BlobsImpl.java b/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/BlobsImpl.java index e89e8972aed35..71311863df22e 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/BlobsImpl.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/BlobsImpl.java @@ -4,20 +4,22 @@ package com.azure.storage.blob.implementation; -import com.azure.core.annotations.DELETE; -import com.azure.core.annotations.ExpectedResponses; -import com.azure.core.annotations.GET; -import com.azure.core.annotations.HEAD; -import com.azure.core.annotations.HeaderParam; -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; import com.azure.core.implementation.DateTimeRfc1123; import com.azure.core.implementation.RestProxy; +import com.azure.core.implementation.annotation.Delete; +import com.azure.core.implementation.annotation.ExpectedResponses; +import com.azure.core.implementation.annotation.Get; +import com.azure.core.implementation.annotation.Head; +import com.azure.core.implementation.annotation.HeaderParam; +import com.azure.core.implementation.annotation.Host; +import com.azure.core.implementation.annotation.HostParam; +import com.azure.core.implementation.annotation.PathParam; +import com.azure.core.implementation.annotation.Put; +import com.azure.core.implementation.annotation.QueryParam; +import com.azure.core.implementation.annotation.ReturnType; +import com.azure.core.implementation.annotation.ServiceInterface; +import com.azure.core.implementation.annotation.ServiceMethod; +import com.azure.core.implementation.annotation.UnexpectedResponseExceptionType; import com.azure.core.implementation.util.Base64Util; import com.azure.core.util.Context; import com.azure.storage.blob.models.AccessTier; @@ -71,7 +73,7 @@ public final class BlobsImpl { * @param client the instance of the service client containing this operation class. */ public BlobsImpl(AzureBlobStorageImpl client) { - this.service = RestProxy.create(BlobsService.class, client); + this.service = RestProxy.create(BlobsService.class, client.httpPipeline()); this.client = client; } @@ -80,89 +82,89 @@ public BlobsImpl(AzureBlobStorageImpl client) { * proxy service to perform REST calls. */ @Host("{url}") - @Service("Storage Blobs") + @ServiceInterface(name = "Blobs") private interface BlobsService { - @GET("{containerName}/{blob}") - @ExpectedResponses({200, 206}) + @Get("{containerName}/{blob}") + @ExpectedResponses({200, 206, 304}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono download(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @QueryParam("snapshot") String snapshot, @QueryParam("versionid") String versionId, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-range") String range, @HeaderParam("x-ms-range-get-content-md5") Boolean rangeGetContentMD5, @QueryParam("x-ms-encryption-key") String encryptionKey, @QueryParam("x-ms-encryption-key-sha256") String encryptionKeySha256, @QueryParam("x-ms-encryption-algorithm") EncryptionAlgorithmType encryptionAlgorithm, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, Context context); - @HEAD("{containerName}/{blob}") - @ExpectedResponses({200}) + @Head("{containerName}/{blob}") + @ExpectedResponses({200, 304}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono getProperties(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @QueryParam("snapshot") String snapshot, @QueryParam("versionid") String versionId, @QueryParam("timeout") Integer timeout, @QueryParam("x-ms-encryption-key") String encryptionKey, @QueryParam("x-ms-encryption-key-sha256") String encryptionKeySha256, @QueryParam("x-ms-encryption-algorithm") EncryptionAlgorithmType encryptionAlgorithm, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, Context context); - @DELETE("{containerName}/{blob}") + @Delete("{containerName}/{blob}") @ExpectedResponses({202}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono delete(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @QueryParam("snapshot") String snapshot, @QueryParam("versionid") String versionId, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-delete-snapshots") DeleteSnapshotsOptionType deleteSnapshots, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, Context context); - @PUT("{containerName}/{blob}") + @Put("{containerName}/{blob}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono undelete(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, Context context); - @PUT("{containerName}/{blob}") + @Put("{containerName}/{blob}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono setHTTPHeaders(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @HeaderParam("x-ms-blob-cache-control") String blobCacheControl, @HeaderParam("x-ms-blob-content-type") String blobContentType, @HeaderParam("x-ms-blob-content-md5") String blobContentMD5, @HeaderParam("x-ms-blob-content-encoding") String blobContentEncoding, @HeaderParam("x-ms-blob-content-language") String blobContentLanguage, @HeaderParam("x-ms-blob-content-disposition") String blobContentDisposition, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, Context context); - @PUT("{containerName}/{blob}") + @Put("{containerName}/{blob}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono setMetadata(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-meta-") Map metadata, @QueryParam("x-ms-encryption-key") String encryptionKey, @QueryParam("x-ms-encryption-key-sha256") String encryptionKeySha256, @QueryParam("x-ms-encryption-algorithm") EncryptionAlgorithmType encryptionAlgorithm, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, Context context); - @PUT("{containerName}/{blob}") + @Put("{containerName}/{blob}") @ExpectedResponses({201}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono acquireLease(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-lease-duration") Integer duration, @HeaderParam("x-ms-proposed-lease-id") String proposedLeaseId, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @HeaderParam("x-ms-lease-action") String action, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, Context context); - @PUT("{containerName}/{blob}") + @Put("{containerName}/{blob}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono releaseLease(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @HeaderParam("x-ms-lease-action") String action, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, Context context); - @PUT("{containerName}/{blob}") + @Put("{containerName}/{blob}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono renewLease(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @HeaderParam("x-ms-lease-action") String action, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, Context context); - @PUT("{containerName}/{blob}") + @Put("{containerName}/{blob}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono changeLease(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("x-ms-proposed-lease-id") String proposedLeaseId, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @HeaderParam("x-ms-lease-action") String action, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, Context context); - @PUT("{containerName}/{blob}") + @Put("{containerName}/{blob}") @ExpectedResponses({202}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono breakLease(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-lease-break-period") Integer breakPeriod, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @HeaderParam("x-ms-lease-action") String action, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, Context context); - @PUT("{containerName}/{blob}") + @Put("{containerName}/{blob}") @ExpectedResponses({201}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono createSnapshot(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-meta-") Map metadata, @QueryParam("x-ms-encryption-key") String encryptionKey, @QueryParam("x-ms-encryption-key-sha256") String encryptionKeySha256, @QueryParam("x-ms-encryption-algorithm") EncryptionAlgorithmType encryptionAlgorithm, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, @HeaderParam("x-ms-lease-id") String leaseId, Context context); - @PUT("{containerName}/{blob}") + @Put("{containerName}/{blob}") @ExpectedResponses({202}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono startCopyFromURL(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-meta-") Map metadata, @HeaderParam("x-ms-copy-source") URL copySource, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @HeaderParam("x-ms-source-if-modified-since") DateTimeRfc1123 sourceIfModifiedSince, @HeaderParam("x-ms-source-if-unmodified-since") DateTimeRfc1123 sourceIfUnmodifiedSince, @HeaderParam("x-ms-source-if-match") String sourceIfMatch, @HeaderParam("x-ms-source-if-none-match") String sourceIfNoneMatch, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, @HeaderParam("x-ms-lease-id") String leaseId, Context context); - @PUT("{containerName}/{blob}") + @Put("{containerName}/{blob}") @ExpectedResponses({202}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono copyFromURL(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-meta-") Map metadata, @HeaderParam("x-ms-copy-source") URL copySource, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @HeaderParam("x-ms-requires-sync") String xMsRequiresSync, @HeaderParam("x-ms-source-if-modified-since") DateTimeRfc1123 sourceIfModifiedSince, @HeaderParam("x-ms-source-if-unmodified-since") DateTimeRfc1123 sourceIfUnmodifiedSince, @HeaderParam("x-ms-source-if-match") String sourceIfMatch, @HeaderParam("x-ms-source-if-none-match") String sourceIfNoneMatch, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, @HeaderParam("x-ms-lease-id") String leaseId, Context context); - @PUT("{containerName}/{blob}") + @Put("{containerName}/{blob}") @ExpectedResponses({204}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono abortCopyFromURL(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @QueryParam("copyid") String copyId, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @HeaderParam("x-ms-copy-action") String copyActionAbortConstant, @HeaderParam("x-ms-lease-id") String leaseId, Context context); - @PUT("{containerName}/{blob}") + @Put("{containerName}/{blob}") @ExpectedResponses({200, 202}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono setTier(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-access-tier") AccessTier tier, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @HeaderParam("x-ms-lease-id") String leaseId, Context context); - @GET("{containerName}/{blob}") + @Get("{containerName}/{blob}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono getAccountInfo(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @HeaderParam("x-ms-version") String version, @QueryParam("restype") String restype, @QueryParam("comp") String comp, Context context); @@ -177,6 +179,7 @@ private interface BlobsService { * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono downloadWithRestResponseAsync(String containerName, String blob, Context context) { final String snapshot = null; final String versionId = null; @@ -215,6 +218,7 @@ public Mono downloadWithRestResponseAsync(String containe * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono downloadWithRestResponseAsync(String containerName, String blob, String snapshot, String versionId, Integer timeout, String range, Boolean rangeGetContentMD5, String encryptionKey, String encryptionKeySha256, EncryptionAlgorithmType encryptionAlgorithm, String requestId, LeaseAccessConditions leaseAccessConditions, ModifiedAccessConditions modifiedAccessConditions, Context context) { String leaseId = null; if (leaseAccessConditions != null) { @@ -250,6 +254,7 @@ public Mono downloadWithRestResponseAsync(String containe * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getPropertiesWithRestResponseAsync(String containerName, String blob, Context context) { final String snapshot = null; final String versionId = null; @@ -284,6 +289,7 @@ public Mono getPropertiesWithRestResponseAsync(Strin * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getPropertiesWithRestResponseAsync(String containerName, String blob, String snapshot, String versionId, Integer timeout, String encryptionKey, String encryptionKeySha256, EncryptionAlgorithmType encryptionAlgorithm, String requestId, LeaseAccessConditions leaseAccessConditions, ModifiedAccessConditions modifiedAccessConditions, Context context) { String leaseId = null; if (leaseAccessConditions != null) { @@ -311,7 +317,7 @@ public Mono getPropertiesWithRestResponseAsync(Strin } /** - * If the storage account's soft delete feature is disabled then, when a blob is deleted, it is permanently removed from the storage account. If the storage account's soft delete feature is enabled, then, when a blob is deleted, it is marked for deletion and becomes inaccessible immediately. However, the storage service retains the blob or snapshot for the number of days specified by the DeleteRetentionPolicy section of [Storage service properties] (Set-Blob-Service-Properties.md). After the specified number of days has passed, the blob's data is permanently removed from the storage account. Note that you continue to be charged for the soft-deleted blob's storage until it is permanently removed. Use the List Blobs API and specify the "include=deleted" query parameter to discover which blobs and snapshots have been soft deleted. You can then use the Undelete Blob API to restore a soft-deleted blob. All other operations on a soft-deleted blob or snapshot causes the service to return an HTTP status code of 404 (ResourceNotFound). If the storage account's automatic snapshot feature is enabled, then, when a blob is deleted, an automatic snapshot is created. The blob becomes inaccessible immediately. All other operations on the blob causes the service to return an HTTP status code of 404 (ResourceNotFound). You can access automatic snapshot using snapshot timestamp or version id. You can restore the blob by calling Put or Copy Blob API with automatic snapshot as source. Deleting automatic snapshot requires shared key or special SAS/RBAC permissions. + * If the storage account's soft delete feature is disabled then, when a blob is deleted, it is permanently removed from the storage account. If the storage account's soft delete feature is enabled, then, when a blob is deleted, it is marked for deletion and becomes inaccessible immediately. However, the blob service retains the blob or snapshot for the number of days specified by the DeleteRetentionPolicy section of [Storage service properties] (Set-Blob-Service-Properties.md). After the specified number of days has passed, the blob's data is permanently removed from the storage account. Note that you continue to be charged for the soft-deleted blob's storage until it is permanently removed. Use the List Blobs API and specify the "include=deleted" query parameter to discover which blobs and snapshots have been soft deleted. You can then use the Undelete Blob API to restore a soft-deleted blob. All other operations on a soft-deleted blob or snapshot causes the service to return an HTTP status code of 404 (ResourceNotFound). If the storage account's automatic snapshot feature is enabled, then, when a blob is deleted, an automatic snapshot is created. The blob becomes inaccessible immediately. All other operations on the blob causes the service to return an HTTP status code of 404 (ResourceNotFound). You can access automatic snapshot using snapshot timestamp or version id. You can restore the blob by calling Put or Copy Blob API with automatic snapshot as source. Deleting automatic snapshot requires shared key or special SAS/RBAC permissions. * * @param containerName The container name. * @param blob The blob name. @@ -319,6 +325,7 @@ public Mono getPropertiesWithRestResponseAsync(Strin * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono deleteWithRestResponseAsync(String containerName, String blob, Context context) { final String snapshot = null; final String versionId = null; @@ -334,7 +341,7 @@ public Mono deleteWithRestResponseAsync(String containerNam } /** - * If the storage account's soft delete feature is disabled then, when a blob is deleted, it is permanently removed from the storage account. If the storage account's soft delete feature is enabled, then, when a blob is deleted, it is marked for deletion and becomes inaccessible immediately. However, the storage service retains the blob or snapshot for the number of days specified by the DeleteRetentionPolicy section of [Storage service properties] (Set-Blob-Service-Properties.md). After the specified number of days has passed, the blob's data is permanently removed from the storage account. Note that you continue to be charged for the soft-deleted blob's storage until it is permanently removed. Use the List Blobs API and specify the "include=deleted" query parameter to discover which blobs and snapshots have been soft deleted. You can then use the Undelete Blob API to restore a soft-deleted blob. All other operations on a soft-deleted blob or snapshot causes the service to return an HTTP status code of 404 (ResourceNotFound). If the storage account's automatic snapshot feature is enabled, then, when a blob is deleted, an automatic snapshot is created. The blob becomes inaccessible immediately. All other operations on the blob causes the service to return an HTTP status code of 404 (ResourceNotFound). You can access automatic snapshot using snapshot timestamp or version id. You can restore the blob by calling Put or Copy Blob API with automatic snapshot as source. Deleting automatic snapshot requires shared key or special SAS/RBAC permissions. + * If the storage account's soft delete feature is disabled then, when a blob is deleted, it is permanently removed from the storage account. If the storage account's soft delete feature is enabled, then, when a blob is deleted, it is marked for deletion and becomes inaccessible immediately. However, the blob service retains the blob or snapshot for the number of days specified by the DeleteRetentionPolicy section of [Storage service properties] (Set-Blob-Service-Properties.md). After the specified number of days has passed, the blob's data is permanently removed from the storage account. Note that you continue to be charged for the soft-deleted blob's storage until it is permanently removed. Use the List Blobs API and specify the "include=deleted" query parameter to discover which blobs and snapshots have been soft deleted. You can then use the Undelete Blob API to restore a soft-deleted blob. All other operations on a soft-deleted blob or snapshot causes the service to return an HTTP status code of 404 (ResourceNotFound). If the storage account's automatic snapshot feature is enabled, then, when a blob is deleted, an automatic snapshot is created. The blob becomes inaccessible immediately. All other operations on the blob causes the service to return an HTTP status code of 404 (ResourceNotFound). You can access automatic snapshot using snapshot timestamp or version id. You can restore the blob by calling Put or Copy Blob API with automatic snapshot as source. Deleting automatic snapshot requires shared key or special SAS/RBAC permissions. * * @param containerName The container name. * @param blob The blob name. @@ -349,6 +356,7 @@ public Mono deleteWithRestResponseAsync(String containerNam * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono deleteWithRestResponseAsync(String containerName, String blob, String snapshot, String versionId, Integer timeout, DeleteSnapshotsOptionType deleteSnapshots, String requestId, LeaseAccessConditions leaseAccessConditions, ModifiedAccessConditions modifiedAccessConditions, Context context) { String leaseId = null; if (leaseAccessConditions != null) { @@ -384,6 +392,7 @@ public Mono deleteWithRestResponseAsync(String containerNam * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono undeleteWithRestResponseAsync(String containerName, String blob, Context context) { final Integer timeout = null; final String requestId = null; @@ -402,6 +411,7 @@ public Mono undeleteWithRestResponseAsync(String containe * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono undeleteWithRestResponseAsync(String containerName, String blob, Integer timeout, String requestId, Context context) { final String comp = "undelete"; return service.undelete(containerName, blob, this.client.url(), timeout, this.client.version(), requestId, comp, context); @@ -416,6 +426,7 @@ public Mono undeleteWithRestResponseAsync(String containe * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono setHTTPHeadersWithRestResponseAsync(String containerName, String blob, Context context) { final Integer timeout = null; final String requestId = null; @@ -448,6 +459,7 @@ public Mono setHTTPHeadersWithRestResponseAsync(Str * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono setHTTPHeadersWithRestResponseAsync(String containerName, String blob, Integer timeout, String requestId, BlobHTTPHeaders blobHTTPHeaders, LeaseAccessConditions leaseAccessConditions, ModifiedAccessConditions modifiedAccessConditions, Context context) { final String comp = "properties"; String blobCacheControl = null; @@ -509,6 +521,7 @@ public Mono setHTTPHeadersWithRestResponseAsync(Str * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono setMetadataWithRestResponseAsync(String containerName, String blob, Context context) { final Integer timeout = null; final Map metadata = null; @@ -542,6 +555,7 @@ public Mono setMetadataWithRestResponseAsync(String co * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono setMetadataWithRestResponseAsync(String containerName, String blob, Integer timeout, Map metadata, String encryptionKey, String encryptionKeySha256, EncryptionAlgorithmType encryptionAlgorithm, String requestId, LeaseAccessConditions leaseAccessConditions, ModifiedAccessConditions modifiedAccessConditions, Context context) { final String comp = "metadata"; String leaseId = null; @@ -578,6 +592,7 @@ public Mono setMetadataWithRestResponseAsync(String co * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono acquireLeaseWithRestResponseAsync(String containerName, String blob, Context context) { final Integer timeout = null; final Integer duration = null; @@ -606,6 +621,7 @@ public Mono acquireLeaseWithRestResponseAsync(String * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono acquireLeaseWithRestResponseAsync(String containerName, String blob, Integer timeout, Integer duration, String proposedLeaseId, String requestId, ModifiedAccessConditions modifiedAccessConditions, Context context) { final String comp = "lease"; final String action = "acquire"; @@ -640,6 +656,7 @@ public Mono acquireLeaseWithRestResponseAsync(String * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono releaseLeaseWithRestResponseAsync(String containerName, String blob, String leaseId, Context context) { final Integer timeout = null; final String requestId = null; @@ -665,6 +682,7 @@ public Mono releaseLeaseWithRestResponseAsync(String * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono releaseLeaseWithRestResponseAsync(String containerName, String blob, String leaseId, Integer timeout, String requestId, ModifiedAccessConditions modifiedAccessConditions, Context context) { final String comp = "lease"; final String action = "release"; @@ -699,6 +717,7 @@ public Mono releaseLeaseWithRestResponseAsync(String * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono renewLeaseWithRestResponseAsync(String containerName, String blob, String leaseId, Context context) { final Integer timeout = null; final String requestId = null; @@ -724,6 +743,7 @@ public Mono renewLeaseWithRestResponseAsync(String cont * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono renewLeaseWithRestResponseAsync(String containerName, String blob, String leaseId, Integer timeout, String requestId, ModifiedAccessConditions modifiedAccessConditions, Context context) { final String comp = "lease"; final String action = "renew"; @@ -759,6 +779,7 @@ public Mono renewLeaseWithRestResponseAsync(String cont * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono changeLeaseWithRestResponseAsync(String containerName, String blob, String leaseId, String proposedLeaseId, Context context) { final Integer timeout = null; final String requestId = null; @@ -785,6 +806,7 @@ public Mono changeLeaseWithRestResponseAsync(String co * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono changeLeaseWithRestResponseAsync(String containerName, String blob, String leaseId, String proposedLeaseId, Integer timeout, String requestId, ModifiedAccessConditions modifiedAccessConditions, Context context) { final String comp = "lease"; final String action = "change"; @@ -818,6 +840,7 @@ public Mono changeLeaseWithRestResponseAsync(String co * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono breakLeaseWithRestResponseAsync(String containerName, String blob, Context context) { final Integer timeout = null; final Integer breakPeriod = null; @@ -844,6 +867,7 @@ public Mono breakLeaseWithRestResponseAsync(String cont * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono breakLeaseWithRestResponseAsync(String containerName, String blob, Integer timeout, Integer breakPeriod, String requestId, ModifiedAccessConditions modifiedAccessConditions, Context context) { final String comp = "lease"; final String action = "break"; @@ -877,6 +901,7 @@ public Mono breakLeaseWithRestResponseAsync(String cont * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono createSnapshotWithRestResponseAsync(String containerName, String blob, Context context) { final Integer timeout = null; final Map metadata = null; @@ -910,6 +935,7 @@ public Mono createSnapshotWithRestResponseAsync(Str * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono createSnapshotWithRestResponseAsync(String containerName, String blob, Integer timeout, Map metadata, String encryptionKey, String encryptionKeySha256, EncryptionAlgorithmType encryptionAlgorithm, String requestId, ModifiedAccessConditions modifiedAccessConditions, LeaseAccessConditions leaseAccessConditions, Context context) { final String comp = "snapshot"; OffsetDateTime ifModifiedSince = null; @@ -947,6 +973,7 @@ public Mono createSnapshotWithRestResponseAsync(Str * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono startCopyFromURLWithRestResponseAsync(String containerName, String blob, URL copySource, Context context) { final Integer timeout = null; final Map metadata = null; @@ -979,6 +1006,7 @@ public Mono startCopyFromURLWithRestResponseAsync * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono startCopyFromURLWithRestResponseAsync(String containerName, String blob, URL copySource, Integer timeout, Map metadata, String requestId, SourceModifiedAccessConditions sourceModifiedAccessConditions, ModifiedAccessConditions modifiedAccessConditions, LeaseAccessConditions leaseAccessConditions, Context context) { OffsetDateTime sourceIfModifiedSince = null; if (sourceModifiedAccessConditions != null) { @@ -1033,6 +1061,7 @@ public Mono startCopyFromURLWithRestResponseAsync * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono copyFromURLWithRestResponseAsync(String containerName, String blob, URL copySource, Context context) { final Integer timeout = null; final Map metadata = null; @@ -1066,6 +1095,7 @@ public Mono copyFromURLWithRestResponseAsync(String co * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono copyFromURLWithRestResponseAsync(String containerName, String blob, URL copySource, Integer timeout, Map metadata, String requestId, SourceModifiedAccessConditions sourceModifiedAccessConditions, ModifiedAccessConditions modifiedAccessConditions, LeaseAccessConditions leaseAccessConditions, Context context) { final String xMsRequiresSync = "true"; OffsetDateTime sourceIfModifiedSince = null; @@ -1121,6 +1151,7 @@ public Mono copyFromURLWithRestResponseAsync(String co * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono abortCopyFromURLWithRestResponseAsync(String containerName, String blob, String copyId, Context context) { final Integer timeout = null; final String requestId = null; @@ -1143,6 +1174,7 @@ public Mono abortCopyFromURLWithRestResponseAsync * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono abortCopyFromURLWithRestResponseAsync(String containerName, String blob, String copyId, Integer timeout, String requestId, LeaseAccessConditions leaseAccessConditions, Context context) { final String comp = "copy"; final String copyActionAbortConstant = "abort"; @@ -1163,6 +1195,7 @@ public Mono abortCopyFromURLWithRestResponseAsync * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono setTierWithRestResponseAsync(String containerName, String blob, AccessTier tier, Context context) { final Integer timeout = null; final String requestId = null; @@ -1184,6 +1217,7 @@ public Mono setTierWithRestResponseAsync(String containerN * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono setTierWithRestResponseAsync(String containerName, String blob, AccessTier tier, Integer timeout, String requestId, LeaseAccessConditions leaseAccessConditions, Context context) { final String comp = "tier"; String leaseId = null; @@ -1202,6 +1236,7 @@ public Mono setTierWithRestResponseAsync(String containerN * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getAccountInfoWithRestResponseAsync(String containerName, String blob, Context context) { final String restype = "account"; final String comp = "properties"; diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/BlockBlobsImpl.java b/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/BlockBlobsImpl.java index 2c4645d2bd4bc..07f3f4f15061b 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/BlockBlobsImpl.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/BlockBlobsImpl.java @@ -4,19 +4,21 @@ package com.azure.storage.blob.implementation; -import com.azure.core.annotations.BodyParam; -import com.azure.core.annotations.ExpectedResponses; -import com.azure.core.annotations.GET; -import com.azure.core.annotations.HeaderParam; -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; import com.azure.core.implementation.DateTimeRfc1123; import com.azure.core.implementation.RestProxy; +import com.azure.core.implementation.annotation.BodyParam; +import com.azure.core.implementation.annotation.ExpectedResponses; +import com.azure.core.implementation.annotation.Get; +import com.azure.core.implementation.annotation.HeaderParam; +import com.azure.core.implementation.annotation.Host; +import com.azure.core.implementation.annotation.HostParam; +import com.azure.core.implementation.annotation.PathParam; +import com.azure.core.implementation.annotation.Put; +import com.azure.core.implementation.annotation.QueryParam; +import com.azure.core.implementation.annotation.ReturnType; +import com.azure.core.implementation.annotation.ServiceInterface; +import com.azure.core.implementation.annotation.ServiceMethod; +import com.azure.core.implementation.annotation.UnexpectedResponseExceptionType; import com.azure.core.implementation.util.Base64Util; import com.azure.core.util.Context; import com.azure.storage.blob.models.BlobHTTPHeaders; @@ -33,12 +35,11 @@ import com.azure.storage.blob.models.SourceModifiedAccessConditions; import com.azure.storage.blob.models.StorageErrorException; import io.netty.buffer.ByteBuf; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - import java.net.URL; import java.time.OffsetDateTime; import java.util.Map; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; /** * An instance of this class provides access to all the operations defined in @@ -61,7 +62,7 @@ public final class BlockBlobsImpl { * @param client the instance of the service client containing this operation class. */ public BlockBlobsImpl(AzureBlobStorageImpl client) { - this.service = RestProxy.create(BlockBlobsService.class, client); + this.service = RestProxy.create(BlockBlobsService.class, client.httpPipeline()); this.client = client; } @@ -70,29 +71,29 @@ public BlockBlobsImpl(AzureBlobStorageImpl client) { * proxy service to perform REST calls. */ @Host("{url}") - @Service("Storage Blobs BlockBlob") + @ServiceInterface(name = "BlockBlobs") private interface BlockBlobsService { - @PUT("{containerName}/{blob}") + @Put("{containerName}/{blob}") @ExpectedResponses({201}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono upload(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @BodyParam("application/octet-stream") Flux body, @QueryParam("timeout") Integer timeout, @HeaderParam("Content-Length") long contentLength, @HeaderParam("x-ms-meta-") Map metadata, @QueryParam("x-ms-encryption-key") String encryptionKey, @QueryParam("x-ms-encryption-key-sha256") String encryptionKeySha256, @QueryParam("x-ms-encryption-algorithm") EncryptionAlgorithmType encryptionAlgorithm, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @HeaderParam("x-ms-blob-type") String blobType, @HeaderParam("x-ms-blob-content-type") String blobContentType, @HeaderParam("x-ms-blob-content-encoding") String blobContentEncoding, @HeaderParam("x-ms-blob-content-language") String blobContentLanguage, @HeaderParam("x-ms-blob-content-md5") String blobContentMD5, @HeaderParam("x-ms-blob-cache-control") String blobCacheControl, @HeaderParam("x-ms-blob-content-disposition") String blobContentDisposition, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, Context context); - @PUT("{containerName}/{blob}") + @Put("{containerName}/{blob}") @ExpectedResponses({201}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono stageBlock(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @QueryParam("blockid") String blockId, @HeaderParam("Content-Length") long contentLength, @HeaderParam("Content-MD5") String transactionalContentMD5, @BodyParam("application/octet-stream") Flux body, @QueryParam("timeout") Integer timeout, @QueryParam("x-ms-encryption-key") String encryptionKey, @QueryParam("x-ms-encryption-key-sha256") String encryptionKeySha256, @QueryParam("x-ms-encryption-algorithm") EncryptionAlgorithmType encryptionAlgorithm, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @HeaderParam("x-ms-lease-id") String leaseId, Context context); - @PUT("{containerName}/{blob}") - @ExpectedResponses({201}) + @Put("{containerName}/{blob}") + @ExpectedResponses({201, 304}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono stageBlockFromURL(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @QueryParam("blockid") String blockId, @HeaderParam("Content-Length") long contentLength, @HeaderParam("x-ms-copy-source") URL copySource, @HeaderParam("x-ms-source-range") String sourceRange, @HeaderParam("x-ms-source-content-md5") String sourceContentMD5, @QueryParam("timeout") Integer timeout, @QueryParam("x-ms-encryption-key") String encryptionKey, @QueryParam("x-ms-encryption-key-sha256") String encryptionKeySha256, @QueryParam("x-ms-encryption-algorithm") EncryptionAlgorithmType encryptionAlgorithm, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("x-ms-source-if-modified-since") DateTimeRfc1123 sourceIfModifiedSince, @HeaderParam("x-ms-source-if-unmodified-since") DateTimeRfc1123 sourceIfUnmodifiedSince, @HeaderParam("x-ms-source-if-match") String sourceIfMatch, @HeaderParam("x-ms-source-if-none-match") String sourceIfNoneMatch, Context context); - @PUT("{containerName}/{blob}") + @Put("{containerName}/{blob}") @ExpectedResponses({201}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono commitBlockList(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-meta-") Map metadata, @QueryParam("x-ms-encryption-key") String encryptionKey, @QueryParam("x-ms-encryption-key-sha256") String encryptionKeySha256, @QueryParam("x-ms-encryption-algorithm") EncryptionAlgorithmType encryptionAlgorithm, @BodyParam("application/xml; charset=utf-8") BlockLookupList blocks, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @HeaderParam("x-ms-blob-cache-control") String blobCacheControl, @HeaderParam("x-ms-blob-content-type") String blobContentType, @HeaderParam("x-ms-blob-content-encoding") String blobContentEncoding, @HeaderParam("x-ms-blob-content-language") String blobContentLanguage, @HeaderParam("x-ms-blob-content-md5") String blobContentMD5, @HeaderParam("x-ms-blob-content-disposition") String blobContentDisposition, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, Context context); - @GET("{containerName}/{blob}") + @Get("{containerName}/{blob}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono getBlockList(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @QueryParam("snapshot") String snapshot, @QueryParam("versionid") String versionId, @QueryParam("blocklisttype") BlockListType listType, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @HeaderParam("x-ms-lease-id") String leaseId, Context context); @@ -109,6 +110,7 @@ private interface BlockBlobsService { * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono uploadWithRestResponseAsync(String containerName, String blob, Flux body, long contentLength, Context context) { final Integer timeout = null; final Map metadata = null; @@ -151,6 +153,7 @@ public Mono uploadWithRestResponseAsync(String contain * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono uploadWithRestResponseAsync(String containerName, String blob, Flux body, long contentLength, Integer timeout, Map metadata, String encryptionKey, String encryptionKeySha256, EncryptionAlgorithmType encryptionAlgorithm, String requestId, BlobHTTPHeaders blobHTTPHeaders, LeaseAccessConditions leaseAccessConditions, ModifiedAccessConditions modifiedAccessConditions, Context context) { final String blobType = "BlockBlob"; String blobContentType = null; @@ -215,6 +218,7 @@ public Mono uploadWithRestResponseAsync(String contain * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono stageBlockWithRestResponseAsync(String containerName, String blob, String blockId, long contentLength, Flux body, Context context) { final Integer timeout = null; final String encryptionKey = null; @@ -246,6 +250,7 @@ public Mono stageBlockWithRestResponseAsync(String * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono stageBlockWithRestResponseAsync(String containerName, String blob, String blockId, long contentLength, Flux body, byte[] transactionalContentMD5, Integer timeout, String encryptionKey, String encryptionKeySha256, EncryptionAlgorithmType encryptionAlgorithm, String requestId, LeaseAccessConditions leaseAccessConditions, Context context) { final String comp = "block"; String leaseId = null; @@ -268,6 +273,7 @@ public Mono stageBlockWithRestResponseAsync(String * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono stageBlockFromURLWithRestResponseAsync(String containerName, String blob, String blockId, long contentLength, URL sourceUrl, Context context) { final String sourceRange = null; final Integer timeout = null; @@ -306,6 +312,7 @@ public Mono stageBlockFromURLWithRestRespon * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono stageBlockFromURLWithRestResponseAsync(String containerName, String blob, String blockId, long contentLength, URL sourceUrl, String sourceRange, byte[] sourceContentMD5, Integer timeout, String encryptionKey, String encryptionKeySha256, EncryptionAlgorithmType encryptionAlgorithm, String requestId, LeaseAccessConditions leaseAccessConditions, SourceModifiedAccessConditions sourceModifiedAccessConditions, Context context) { final String comp = "block"; String leaseId = null; @@ -344,6 +351,7 @@ public Mono stageBlockFromURLWithRestRespon * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono commitBlockListWithRestResponseAsync(String containerName, String blob, BlockLookupList blocks, Context context) { final Integer timeout = null; final Map metadata = null; @@ -385,6 +393,7 @@ public Mono commitBlockListWithRestResponseAs * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono commitBlockListWithRestResponseAsync(String containerName, String blob, BlockLookupList blocks, Integer timeout, Map metadata, String encryptionKey, String encryptionKeySha256, EncryptionAlgorithmType encryptionAlgorithm, String requestId, BlobHTTPHeaders blobHTTPHeaders, LeaseAccessConditions leaseAccessConditions, ModifiedAccessConditions modifiedAccessConditions, Context context) { final String comp = "blocklist"; String blobCacheControl = null; @@ -447,6 +456,7 @@ public Mono commitBlockListWithRestResponseAs * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getBlockListWithRestResponseAsync(String containerName, String blob, BlockListType listType, Context context) { final String snapshot = null; final String versionId = null; @@ -472,6 +482,7 @@ public Mono getBlockListWithRestResponseAsync(St * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getBlockListWithRestResponseAsync(String containerName, String blob, BlockListType listType, String snapshot, String versionId, Integer timeout, String requestId, LeaseAccessConditions leaseAccessConditions, Context context) { final String comp = "blocklist"; String leaseId = null; diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/ContainersImpl.java b/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/ContainersImpl.java index 780b3a356a619..6070cff261a33 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/ContainersImpl.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/ContainersImpl.java @@ -4,21 +4,23 @@ package com.azure.storage.blob.implementation; -import com.azure.core.annotations.BodyParam; -import com.azure.core.annotations.DELETE; -import com.azure.core.annotations.ExpectedResponses; -import com.azure.core.annotations.GET; -import com.azure.core.annotations.HeaderParam; -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; import com.azure.core.implementation.CollectionFormat; import com.azure.core.implementation.DateTimeRfc1123; import com.azure.core.implementation.RestProxy; +import com.azure.core.implementation.annotation.BodyParam; +import com.azure.core.implementation.annotation.Delete; +import com.azure.core.implementation.annotation.ExpectedResponses; +import com.azure.core.implementation.annotation.Get; +import com.azure.core.implementation.annotation.HeaderParam; +import com.azure.core.implementation.annotation.Host; +import com.azure.core.implementation.annotation.HostParam; +import com.azure.core.implementation.annotation.PathParam; +import com.azure.core.implementation.annotation.Put; +import com.azure.core.implementation.annotation.QueryParam; +import com.azure.core.implementation.annotation.ReturnType; +import com.azure.core.implementation.annotation.ServiceInterface; +import com.azure.core.implementation.annotation.ServiceMethod; +import com.azure.core.implementation.annotation.UnexpectedResponseExceptionType; import com.azure.core.implementation.serializer.jackson.JacksonAdapter; import com.azure.core.util.Context; import com.azure.storage.blob.models.ContainersAcquireLeaseResponse; @@ -68,7 +70,7 @@ public final class ContainersImpl { * @param client the instance of the service client containing this operation class. */ public ContainersImpl(AzureBlobStorageImpl client) { - this.service = RestProxy.create(ContainersService.class, client); + this.service = RestProxy.create(ContainersService.class, client.httpPipeline()); this.client = client; } @@ -77,74 +79,74 @@ public ContainersImpl(AzureBlobStorageImpl client) { * proxy service to perform REST calls. */ @Host("{url}") - @Service("Storage Blobs Containers") + @ServiceInterface(name = "Containers") private interface ContainersService { - @PUT("{containerName}") + @Put("{containerName}") @ExpectedResponses({201}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono create(@PathParam("containerName") String containerName, @HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-meta-") Map metadata, @HeaderParam("x-ms-blob-public-access") PublicAccessType access, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("restype") String restype, Context context); - @GET("{containerName}") + @Get("{containerName}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono getProperties(@PathParam("containerName") String containerName, @HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("restype") String restype, @HeaderParam("x-ms-lease-id") String leaseId, Context context); - @DELETE("{containerName}") + @Delete("{containerName}") @ExpectedResponses({202}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono delete(@PathParam("containerName") String containerName, @HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("restype") String restype, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, Context context); - @PUT("{containerName}") + @Put("{containerName}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono setMetadata(@PathParam("containerName") String containerName, @HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-meta-") Map metadata, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("restype") String restype, @QueryParam("comp") String comp, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, Context context); - @GET("{containerName}") + @Get("{containerName}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono getAccessPolicy(@PathParam("containerName") String containerName, @HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("restype") String restype, @QueryParam("comp") String comp, @HeaderParam("x-ms-lease-id") String leaseId, Context context); - @PUT("{containerName}") + @Put("{containerName}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono setAccessPolicy(@PathParam("containerName") String containerName, @HostParam("url") String url, @BodyParam("application/xml; charset=utf-8") SignedIdentifiersWrapper containerAcl, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-blob-public-access") PublicAccessType access, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("restype") String restype, @QueryParam("comp") String comp, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, Context context); - @PUT("{containerName}") + @Put("{containerName}") @ExpectedResponses({201}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono acquireLease(@PathParam("containerName") String containerName, @HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-lease-duration") Integer duration, @HeaderParam("x-ms-proposed-lease-id") String proposedLeaseId, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @QueryParam("restype") String restype, @HeaderParam("x-ms-lease-action") String action, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, Context context); - @PUT("{containerName}") + @Put("{containerName}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono releaseLease(@PathParam("containerName") String containerName, @HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @QueryParam("restype") String restype, @HeaderParam("x-ms-lease-action") String action, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, Context context); - @PUT("{containerName}") + @Put("{containerName}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono renewLease(@PathParam("containerName") String containerName, @HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @QueryParam("restype") String restype, @HeaderParam("x-ms-lease-action") String action, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, Context context); - @PUT("{containerName}") + @Put("{containerName}") @ExpectedResponses({202}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono breakLease(@PathParam("containerName") String containerName, @HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-lease-break-period") Integer breakPeriod, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @QueryParam("restype") String restype, @HeaderParam("x-ms-lease-action") String action, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, Context context); - @PUT("{containerName}") + @Put("{containerName}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono changeLease(@PathParam("containerName") String containerName, @HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("x-ms-proposed-lease-id") String proposedLeaseId, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @QueryParam("restype") String restype, @HeaderParam("x-ms-lease-action") String action, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, Context context); - @GET("{containerName}") + @Get("{containerName}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono listBlobFlatSegment(@PathParam("containerName") String containerName, @HostParam("url") String url, @QueryParam("prefix") String prefix, @QueryParam("marker") String marker, @QueryParam("maxresults") Integer maxresults, @QueryParam("include") String include, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("restype") String restype, @QueryParam("comp") String comp, Context context); - @GET("{containerName}") + @Get("{containerName}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono listBlobHierarchySegment(@PathParam("containerName") String containerName, @HostParam("url") String url, @QueryParam("prefix") String prefix, @QueryParam("delimiter") String delimiter, @QueryParam("marker") String marker, @QueryParam("maxresults") Integer maxresults, @QueryParam("include") String include, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("restype") String restype, @QueryParam("comp") String comp, Context context); - @GET("{containerName}") + @Get("{containerName}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono getAccountInfo(@PathParam("containerName") String containerName, @HostParam("url") String url, @HeaderParam("x-ms-version") String version, @QueryParam("restype") String restype, @QueryParam("comp") String comp, Context context); @@ -158,6 +160,7 @@ private interface ContainersService { * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono createWithRestResponseAsync(String containerName, Context context) { final Integer timeout = null; final Map metadata = null; @@ -179,6 +182,7 @@ public Mono createWithRestResponseAsync(String contain * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono createWithRestResponseAsync(String containerName, Integer timeout, Map metadata, PublicAccessType access, String requestId, Context context) { final String restype = "container"; return service.create(containerName, this.client.url(), timeout, metadata, access, this.client.version(), requestId, restype, context); @@ -192,6 +196,7 @@ public Mono createWithRestResponseAsync(String contain * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getPropertiesWithRestResponseAsync(String containerName, Context context) { final Integer timeout = null; final String requestId = null; @@ -211,6 +216,7 @@ public Mono getPropertiesWithRestResponseAsync( * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getPropertiesWithRestResponseAsync(String containerName, Integer timeout, String requestId, LeaseAccessConditions leaseAccessConditions, Context context) { final String restype = "container"; String leaseId = null; @@ -228,6 +234,7 @@ public Mono getPropertiesWithRestResponseAsync( * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono deleteWithRestResponseAsync(String containerName, Context context) { final Integer timeout = null; final String requestId = null; @@ -250,6 +257,7 @@ public Mono deleteWithRestResponseAsync(String contain * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono deleteWithRestResponseAsync(String containerName, Integer timeout, String requestId, LeaseAccessConditions leaseAccessConditions, ModifiedAccessConditions modifiedAccessConditions, Context context) { final String restype = "container"; String leaseId = null; @@ -277,6 +285,7 @@ public Mono deleteWithRestResponseAsync(String contain * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono setMetadataWithRestResponseAsync(String containerName, Context context) { final Integer timeout = null; final Map metadata = null; @@ -301,6 +310,7 @@ public Mono setMetadataWithRestResponseAsync(Stri * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono setMetadataWithRestResponseAsync(String containerName, Integer timeout, Map metadata, String requestId, LeaseAccessConditions leaseAccessConditions, ModifiedAccessConditions modifiedAccessConditions, Context context) { final String restype = "container"; final String comp = "metadata"; @@ -324,6 +334,7 @@ public Mono setMetadataWithRestResponseAsync(Stri * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getAccessPolicyWithRestResponseAsync(String containerName, Context context) { final Integer timeout = null; final String requestId = null; @@ -344,6 +355,7 @@ public Mono getAccessPolicyWithRestResponseAs * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getAccessPolicyWithRestResponseAsync(String containerName, Integer timeout, String requestId, LeaseAccessConditions leaseAccessConditions, Context context) { final String restype = "container"; final String comp = "acl"; @@ -362,6 +374,7 @@ public Mono getAccessPolicyWithRestResponseAs * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono setAccessPolicyWithRestResponseAsync(String containerName, Context context) { final Integer timeout = null; final PublicAccessType access = null; @@ -389,6 +402,7 @@ public Mono setAccessPolicyWithRestResponseAs * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono setAccessPolicyWithRestResponseAsync(String containerName, List containerAcl, Integer timeout, PublicAccessType access, String requestId, LeaseAccessConditions leaseAccessConditions, ModifiedAccessConditions modifiedAccessConditions, Context context) { final String restype = "container"; final String comp = "acl"; @@ -418,6 +432,7 @@ public Mono setAccessPolicyWithRestResponseAs * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono acquireLeaseWithRestResponseAsync(String containerName, Context context) { final Integer timeout = null; final Integer duration = null; @@ -444,6 +459,7 @@ public Mono acquireLeaseWithRestResponseAsync(St * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono acquireLeaseWithRestResponseAsync(String containerName, Integer timeout, Integer duration, String proposedLeaseId, String requestId, ModifiedAccessConditions modifiedAccessConditions, Context context) { final String comp = "lease"; final String restype = "container"; @@ -470,6 +486,7 @@ public Mono acquireLeaseWithRestResponseAsync(St * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono releaseLeaseWithRestResponseAsync(String containerName, String leaseId, Context context) { final Integer timeout = null; final String requestId = null; @@ -493,6 +510,7 @@ public Mono releaseLeaseWithRestResponseAsync(St * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono releaseLeaseWithRestResponseAsync(String containerName, String leaseId, Integer timeout, String requestId, ModifiedAccessConditions modifiedAccessConditions, Context context) { final String comp = "lease"; final String restype = "container"; @@ -519,6 +537,7 @@ public Mono releaseLeaseWithRestResponseAsync(St * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono renewLeaseWithRestResponseAsync(String containerName, String leaseId, Context context) { final Integer timeout = null; final String requestId = null; @@ -542,6 +561,7 @@ public Mono renewLeaseWithRestResponseAsync(String * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono renewLeaseWithRestResponseAsync(String containerName, String leaseId, Integer timeout, String requestId, ModifiedAccessConditions modifiedAccessConditions, Context context) { final String comp = "lease"; final String restype = "container"; @@ -567,6 +587,7 @@ public Mono renewLeaseWithRestResponseAsync(String * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono breakLeaseWithRestResponseAsync(String containerName, Context context) { final Integer timeout = null; final Integer breakPeriod = null; @@ -591,6 +612,7 @@ public Mono breakLeaseWithRestResponseAsync(String * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono breakLeaseWithRestResponseAsync(String containerName, Integer timeout, Integer breakPeriod, String requestId, ModifiedAccessConditions modifiedAccessConditions, Context context) { final String comp = "lease"; final String restype = "container"; @@ -618,6 +640,7 @@ public Mono breakLeaseWithRestResponseAsync(String * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono changeLeaseWithRestResponseAsync(String containerName, String leaseId, String proposedLeaseId, Context context) { final Integer timeout = null; final String requestId = null; @@ -642,6 +665,7 @@ public Mono changeLeaseWithRestResponseAsync(Stri * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono changeLeaseWithRestResponseAsync(String containerName, String leaseId, String proposedLeaseId, Integer timeout, String requestId, ModifiedAccessConditions modifiedAccessConditions, Context context) { final String comp = "lease"; final String restype = "container"; @@ -667,6 +691,7 @@ public Mono changeLeaseWithRestResponseAsync(Stri * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono listBlobFlatSegmentWithRestResponseAsync(String containerName, Context context) { final String prefix = null; final String marker = null; @@ -693,6 +718,7 @@ public Mono listBlobFlatSegmentWithRestRe * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono listBlobFlatSegmentWithRestResponseAsync(String containerName, String prefix, String marker, Integer maxresults, List include, Integer timeout, String requestId, Context context) { final String restype = "container"; final String comp = "list"; @@ -709,6 +735,7 @@ public Mono listBlobFlatSegmentWithRestRe * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono listBlobHierarchySegmentWithRestResponseAsync(String containerName, String delimiter, Context context) { final String prefix = null; final String marker = null; @@ -736,6 +763,7 @@ public Mono listBlobHierarchySegment * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono listBlobHierarchySegmentWithRestResponseAsync(String containerName, String delimiter, String prefix, String marker, Integer maxresults, List include, Integer timeout, String requestId, Context context) { final String restype = "container"; final String comp = "list"; @@ -751,6 +779,7 @@ public Mono listBlobHierarchySegment * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getAccountInfoWithRestResponseAsync(String containerName, Context context) { final String restype = "account"; final String comp = "properties"; diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/PageBlobsImpl.java b/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/PageBlobsImpl.java index f6f6d23380cd6..2f851914b9067 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/PageBlobsImpl.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/PageBlobsImpl.java @@ -4,19 +4,21 @@ package com.azure.storage.blob.implementation; -import com.azure.core.annotations.BodyParam; -import com.azure.core.annotations.ExpectedResponses; -import com.azure.core.annotations.GET; -import com.azure.core.annotations.HeaderParam; -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; import com.azure.core.implementation.DateTimeRfc1123; import com.azure.core.implementation.RestProxy; +import com.azure.core.implementation.annotation.BodyParam; +import com.azure.core.implementation.annotation.ExpectedResponses; +import com.azure.core.implementation.annotation.Get; +import com.azure.core.implementation.annotation.HeaderParam; +import com.azure.core.implementation.annotation.Host; +import com.azure.core.implementation.annotation.HostParam; +import com.azure.core.implementation.annotation.PathParam; +import com.azure.core.implementation.annotation.Put; +import com.azure.core.implementation.annotation.QueryParam; +import com.azure.core.implementation.annotation.ReturnType; +import com.azure.core.implementation.annotation.ServiceInterface; +import com.azure.core.implementation.annotation.ServiceMethod; +import com.azure.core.implementation.annotation.UnexpectedResponseExceptionType; import com.azure.core.implementation.util.Base64Util; import com.azure.core.util.Context; import com.azure.storage.blob.models.BlobHTTPHeaders; @@ -37,12 +39,11 @@ import com.azure.storage.blob.models.SourceModifiedAccessConditions; import com.azure.storage.blob.models.StorageErrorException; import io.netty.buffer.ByteBuf; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - import java.net.URL; import java.time.OffsetDateTime; import java.util.Map; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; /** * An instance of this class provides access to all the operations defined in @@ -65,7 +66,7 @@ public final class PageBlobsImpl { * @param client the instance of the service client containing this operation class. */ public PageBlobsImpl(AzureBlobStorageImpl client) { - this.service = RestProxy.create(PageBlobsService.class, client); + this.service = RestProxy.create(PageBlobsService.class, client.httpPipeline()); this.client = client; } @@ -74,49 +75,49 @@ public PageBlobsImpl(AzureBlobStorageImpl client) { * proxy service to perform REST calls. */ @Host("{url}") - @Service("Storage Blobs PageBlobs") + @ServiceInterface(name = "PageBlobs") private interface PageBlobsService { - @PUT("{containerName}/{blob}") + @Put("{containerName}/{blob}") @ExpectedResponses({201}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono create(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("Content-Length") long contentLength, @HeaderParam("x-ms-meta-") Map metadata, @QueryParam("x-ms-encryption-key") String encryptionKey, @QueryParam("x-ms-encryption-key-sha256") String encryptionKeySha256, @QueryParam("x-ms-encryption-algorithm") EncryptionAlgorithmType encryptionAlgorithm, @HeaderParam("x-ms-blob-content-length") long blobContentLength, @HeaderParam("x-ms-blob-sequence-number") Long blobSequenceNumber, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @HeaderParam("x-ms-blob-type") String blobType, @HeaderParam("x-ms-blob-content-type") String blobContentType, @HeaderParam("x-ms-blob-content-encoding") String blobContentEncoding, @HeaderParam("x-ms-blob-content-language") String blobContentLanguage, @HeaderParam("x-ms-blob-content-md5") String blobContentMD5, @HeaderParam("x-ms-blob-cache-control") String blobCacheControl, @HeaderParam("x-ms-blob-content-disposition") String blobContentDisposition, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, Context context); - @PUT("{containerName}/{blob}") + @Put("{containerName}/{blob}") @ExpectedResponses({201}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono uploadPages(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @BodyParam("application/octet-stream") Flux body, @HeaderParam("Content-Length") long contentLength, @HeaderParam("Content-MD5") String transactionalContentMD5, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-range") String range, @QueryParam("x-ms-encryption-key") String encryptionKey, @QueryParam("x-ms-encryption-key-sha256") String encryptionKeySha256, @QueryParam("x-ms-encryption-algorithm") EncryptionAlgorithmType encryptionAlgorithm, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @HeaderParam("x-ms-page-write") String pageWrite, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("x-ms-if-sequence-number-le") Long ifSequenceNumberLessThanOrEqualTo, @HeaderParam("x-ms-if-sequence-number-lt") Long ifSequenceNumberLessThan, @HeaderParam("x-ms-if-sequence-number-eq") Long ifSequenceNumberEqualTo, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, Context context); - @PUT("{containerName}/{blob}") + @Put("{containerName}/{blob}") @ExpectedResponses({201}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono clearPages(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @HeaderParam("Content-Length") long contentLength, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-range") String range, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @HeaderParam("x-ms-page-write") String pageWrite, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("x-ms-if-sequence-number-le") Long ifSequenceNumberLessThanOrEqualTo, @HeaderParam("x-ms-if-sequence-number-lt") Long ifSequenceNumberLessThan, @HeaderParam("x-ms-if-sequence-number-eq") Long ifSequenceNumberEqualTo, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, Context context); - @PUT("{containerName}/{blob}") - @ExpectedResponses({201}) + @Put("{containerName}/{blob}") + @ExpectedResponses({201, 304}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono uploadPagesFromURL(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @HeaderParam("x-ms-copy-source") URL copySource, @HeaderParam("x-ms-source-range") String sourceRange, @HeaderParam("x-ms-source-content-md5") String sourceContentMD5, @HeaderParam("Content-Length") long contentLength, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-range") String range, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @HeaderParam("x-ms-page-write") String pageWrite, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("x-ms-if-sequence-number-le") Long ifSequenceNumberLessThanOrEqualTo, @HeaderParam("x-ms-if-sequence-number-lt") Long ifSequenceNumberLessThan, @HeaderParam("x-ms-if-sequence-number-eq") Long ifSequenceNumberEqualTo, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, @HeaderParam("x-ms-source-if-modified-since") DateTimeRfc1123 sourceIfModifiedSince, @HeaderParam("x-ms-source-if-unmodified-since") DateTimeRfc1123 sourceIfUnmodifiedSince, @HeaderParam("x-ms-source-if-match") String sourceIfMatch, @HeaderParam("x-ms-source-if-none-match") String sourceIfNoneMatch, Context context); - @GET("{containerName}/{blob}") - @ExpectedResponses({200}) + @Get("{containerName}/{blob}") + @ExpectedResponses({200, 304}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono getPageRanges(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @QueryParam("snapshot") String snapshot, @QueryParam("versionid") String versionId, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-range") String range, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, Context context); - @GET("{containerName}/{blob}") - @ExpectedResponses({200}) + @Get("{containerName}/{blob}") + @ExpectedResponses({200, 304}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono getPageRangesDiff(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @QueryParam("snapshot") String snapshot, @QueryParam("versionid") String versionId, @QueryParam("timeout") Integer timeout, @QueryParam("prevsnapshot") String prevsnapshot, @HeaderParam("x-ms-range") String range, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, Context context); - @PUT("{containerName}/{blob}") + @Put("{containerName}/{blob}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono resize(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-blob-content-length") long blobContentLength, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, Context context); - @PUT("{containerName}/{blob}") + @Put("{containerName}/{blob}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono updateSequenceNumber(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-sequence-number-action") SequenceNumberActionType sequenceNumberAction, @HeaderParam("x-ms-blob-sequence-number") Long blobSequenceNumber, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, Context context); - @PUT("{containerName}/{blob}") + @Put("{containerName}/{blob}") @ExpectedResponses({202}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono copyIncremental(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-copy-source") URL copySource, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, Context context); @@ -133,6 +134,7 @@ private interface PageBlobsService { * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono createWithRestResponseAsync(String containerName, String blob, long contentLength, long blobContentLength, Context context) { final Integer timeout = null; final Map metadata = null; @@ -177,6 +179,7 @@ public Mono createWithRestResponseAsync(String containe * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono createWithRestResponseAsync(String containerName, String blob, long contentLength, long blobContentLength, Integer timeout, Map metadata, String encryptionKey, String encryptionKeySha256, EncryptionAlgorithmType encryptionAlgorithm, Long blobSequenceNumber, String requestId, BlobHTTPHeaders blobHTTPHeaders, LeaseAccessConditions leaseAccessConditions, ModifiedAccessConditions modifiedAccessConditions, Context context) { final String blobType = "PageBlob"; String blobContentType = null; @@ -240,6 +243,7 @@ public Mono createWithRestResponseAsync(String containe * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono uploadPagesWithRestResponseAsync(String containerName, String blob, Flux body, long contentLength, Context context) { final Integer timeout = null; final String range = null; @@ -282,6 +286,7 @@ public Mono uploadPagesWithRestResponseAsync(Strin * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono uploadPagesWithRestResponseAsync(String containerName, String blob, Flux body, long contentLength, byte[] transactionalContentMD5, Integer timeout, String range, String encryptionKey, String encryptionKeySha256, EncryptionAlgorithmType encryptionAlgorithm, String requestId, LeaseAccessConditions leaseAccessConditions, SequenceNumberAccessConditions sequenceNumberAccessConditions, ModifiedAccessConditions modifiedAccessConditions, Context context) { final String comp = "page"; final String pageWrite = "update"; @@ -333,6 +338,7 @@ public Mono uploadPagesWithRestResponseAsync(Strin * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono clearPagesWithRestResponseAsync(String containerName, String blob, long contentLength, Context context) { final Integer timeout = null; final String range = null; @@ -366,6 +372,7 @@ public Mono clearPagesWithRestResponseAsync(String * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono clearPagesWithRestResponseAsync(String containerName, String blob, long contentLength, Integer timeout, String range, String requestId, LeaseAccessConditions leaseAccessConditions, SequenceNumberAccessConditions sequenceNumberAccessConditions, ModifiedAccessConditions modifiedAccessConditions, Context context) { final String comp = "page"; final String pageWrite = "clear"; @@ -419,6 +426,7 @@ public Mono clearPagesWithRestResponseAsync(String * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono uploadPagesFromURLWithRestResponseAsync(String containerName, String blob, URL sourceUrl, String sourceRange, long contentLength, String range, Context context) { final Integer timeout = null; final String requestId = null; @@ -460,6 +468,7 @@ public Mono uploadPagesFromURLWithRestRespo * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono uploadPagesFromURLWithRestResponseAsync(String containerName, String blob, URL sourceUrl, String sourceRange, long contentLength, String range, byte[] sourceContentMD5, Integer timeout, String requestId, LeaseAccessConditions leaseAccessConditions, SequenceNumberAccessConditions sequenceNumberAccessConditions, ModifiedAccessConditions modifiedAccessConditions, SourceModifiedAccessConditions sourceModifiedAccessConditions, Context context) { final String comp = "page"; final String pageWrite = "update"; @@ -528,6 +537,7 @@ public Mono uploadPagesFromURLWithRestRespo * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getPageRangesWithRestResponseAsync(String containerName, String blob, Context context) { final String snapshot = null; final String versionId = null; @@ -559,6 +569,7 @@ public Mono getPageRangesWithRestResponseAsync(S * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getPageRangesWithRestResponseAsync(String containerName, String blob, String snapshot, String versionId, Integer timeout, String range, String requestId, LeaseAccessConditions leaseAccessConditions, ModifiedAccessConditions modifiedAccessConditions, Context context) { final String comp = "pagelist"; String leaseId = null; @@ -595,6 +606,7 @@ public Mono getPageRangesWithRestResponseAsync(S * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getPageRangesDiffWithRestResponseAsync(String containerName, String blob, Context context) { final String snapshot = null; final String versionId = null; @@ -628,6 +640,7 @@ public Mono getPageRangesDiffWithRestRespons * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getPageRangesDiffWithRestResponseAsync(String containerName, String blob, String snapshot, String versionId, Integer timeout, String prevsnapshot, String range, String requestId, LeaseAccessConditions leaseAccessConditions, ModifiedAccessConditions modifiedAccessConditions, Context context) { final String comp = "pagelist"; String leaseId = null; @@ -665,6 +678,7 @@ public Mono getPageRangesDiffWithRestRespons * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono resizeWithRestResponseAsync(String containerName, String blob, long blobContentLength, Context context) { final Integer timeout = null; final String requestId = null; @@ -691,6 +705,7 @@ public Mono resizeWithRestResponseAsync(String containe * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono resizeWithRestResponseAsync(String containerName, String blob, long blobContentLength, Integer timeout, String requestId, LeaseAccessConditions leaseAccessConditions, ModifiedAccessConditions modifiedAccessConditions, Context context) { final String comp = "properties"; String leaseId = null; @@ -728,6 +743,7 @@ public Mono resizeWithRestResponseAsync(String containe * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono updateSequenceNumberWithRestResponseAsync(String containerName, String blob, SequenceNumberActionType sequenceNumberAction, Context context) { final Integer timeout = null; final Long blobSequenceNumber = 0L; @@ -756,6 +772,7 @@ public Mono updateSequenceNumberWithRestR * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono updateSequenceNumberWithRestResponseAsync(String containerName, String blob, SequenceNumberActionType sequenceNumberAction, Integer timeout, Long blobSequenceNumber, String requestId, LeaseAccessConditions leaseAccessConditions, ModifiedAccessConditions modifiedAccessConditions, Context context) { final String comp = "properties"; String leaseId = null; @@ -793,6 +810,7 @@ public Mono updateSequenceNumberWithRestR * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono copyIncrementalWithRestResponseAsync(String containerName, String blob, URL copySource, Context context) { final Integer timeout = null; final String requestId = null; @@ -817,6 +835,7 @@ public Mono copyIncrementalWithRestResponseAsy * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono copyIncrementalWithRestResponseAsync(String containerName, String blob, URL copySource, Integer timeout, String requestId, ModifiedAccessConditions modifiedAccessConditions, Context context) { final String comp = "incrementalcopy"; OffsetDateTime ifModifiedSince = null; diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/ServicesImpl.java b/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/ServicesImpl.java index a31982006724c..1720197cee69c 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/ServicesImpl.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/ServicesImpl.java @@ -4,18 +4,20 @@ package com.azure.storage.blob.implementation; -import com.azure.core.annotations.BodyParam; -import com.azure.core.annotations.ExpectedResponses; -import com.azure.core.annotations.GET; -import com.azure.core.annotations.HeaderParam; -import com.azure.core.annotations.Host; -import com.azure.core.annotations.HostParam; -import com.azure.core.annotations.POST; -import com.azure.core.annotations.PUT; -import com.azure.core.annotations.QueryParam; -import com.azure.core.annotations.Service; -import com.azure.core.annotations.UnexpectedResponseExceptionType; import com.azure.core.implementation.RestProxy; +import com.azure.core.implementation.annotation.BodyParam; +import com.azure.core.implementation.annotation.ExpectedResponses; +import com.azure.core.implementation.annotation.Get; +import com.azure.core.implementation.annotation.HeaderParam; +import com.azure.core.implementation.annotation.Host; +import com.azure.core.implementation.annotation.HostParam; +import com.azure.core.implementation.annotation.Post; +import com.azure.core.implementation.annotation.Put; +import com.azure.core.implementation.annotation.QueryParam; +import com.azure.core.implementation.annotation.ReturnType; +import com.azure.core.implementation.annotation.ServiceInterface; +import com.azure.core.implementation.annotation.ServiceMethod; +import com.azure.core.implementation.annotation.UnexpectedResponseExceptionType; import com.azure.core.util.Context; import com.azure.storage.blob.models.KeyInfo; import com.azure.storage.blob.models.ListContainersIncludeType; @@ -50,7 +52,7 @@ public final class ServicesImpl { * @param client the instance of the service client containing this operation class. */ public ServicesImpl(AzureBlobStorageImpl client) { - this.service = RestProxy.create(ServicesService.class, client); + this.service = RestProxy.create(ServicesService.class, client.httpPipeline()); this.client = client; } @@ -59,34 +61,34 @@ public ServicesImpl(AzureBlobStorageImpl client) { * proxy service to perform REST calls. */ @Host("{url}") - @Service("Storage Blobs Service") + @ServiceInterface(name = "Services") private interface ServicesService { - @PUT("") + @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, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("restype") String restype, @QueryParam("comp") String comp, Context context); - @GET("") + @Get("") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono getProperties(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("restype") String restype, @QueryParam("comp") String comp, Context context); - @GET("") + @Get("") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono getStatistics(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("restype") String restype, @QueryParam("comp") String comp, Context context); - @GET("") + @Get("") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono listContainersSegment(@HostParam("url") String url, @QueryParam("prefix") String prefix, @QueryParam("marker") String marker, @QueryParam("maxresults") Integer maxresults, @QueryParam("include") ListContainersIncludeType include, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, Context context); - @POST("") + @Post("") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono getUserDelegationKey(@HostParam("url") String url, @BodyParam("application/xml; charset=utf-8") KeyInfo keyInfo, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("restype") String restype, @QueryParam("comp") String comp, Context context); - @GET("") + @Get("") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono getAccountInfo(@HostParam("url") String url, @HeaderParam("x-ms-version") String version, @QueryParam("restype") String restype, @QueryParam("comp") String comp, Context context); @@ -100,6 +102,7 @@ private interface ServicesService { * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono setPropertiesWithRestResponseAsync(StorageServiceProperties storageServiceProperties, Context context) { final Integer timeout = null; final String requestId = null; @@ -118,6 +121,7 @@ public Mono setPropertiesWithRestResponseAsync(St * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono setPropertiesWithRestResponseAsync(StorageServiceProperties storageServiceProperties, Integer timeout, String requestId, Context context) { final String restype = "service"; final String comp = "properties"; @@ -131,6 +135,7 @@ public Mono setPropertiesWithRestResponseAsync(St * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getPropertiesWithRestResponseAsync(Context context) { final Integer timeout = null; final String requestId = null; @@ -148,6 +153,7 @@ public Mono getPropertiesWithRestResponseAsync(Co * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getPropertiesWithRestResponseAsync(Integer timeout, String requestId, Context context) { final String restype = "service"; final String comp = "properties"; @@ -161,6 +167,7 @@ public Mono getPropertiesWithRestResponseAsync(In * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getStatisticsWithRestResponseAsync(Context context) { final Integer timeout = null; final String requestId = null; @@ -178,6 +185,7 @@ public Mono getStatisticsWithRestResponseAsync(Co * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getStatisticsWithRestResponseAsync(Integer timeout, String requestId, Context context) { final String restype = "service"; final String comp = "stats"; @@ -191,6 +199,7 @@ public Mono getStatisticsWithRestResponseAsync(In * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono listContainersSegmentWithRestResponseAsync(Context context) { final String prefix = null; final String marker = null; @@ -215,6 +224,7 @@ public Mono listContainersSegmentWithRest * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono listContainersSegmentWithRestResponseAsync(String prefix, String marker, Integer maxresults, ListContainersIncludeType include, Integer timeout, String requestId, Context context) { final String comp = "list"; return service.listContainersSegment(this.client.url(), prefix, marker, maxresults, include, timeout, this.client.version(), requestId, comp, context); @@ -228,6 +238,7 @@ public Mono listContainersSegmentWithRest * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getUserDelegationKeyWithRestResponseAsync(KeyInfo keyInfo, Context context) { final Integer timeout = null; final String requestId = null; @@ -246,6 +257,7 @@ public Mono getUserDelegationKeyWithRestRe * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getUserDelegationKeyWithRestResponseAsync(KeyInfo keyInfo, Integer timeout, String requestId, Context context) { final String restype = "service"; final String comp = "userdelegationkey"; @@ -259,6 +271,7 @@ public Mono getUserDelegationKeyWithRestRe * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getAccountInfoWithRestResponseAsync(Context context) { final String restype = "account"; final String comp = "properties"; diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/SignedIdentifiersWrapper.java b/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/SignedIdentifiersWrapper.java index 41bac045975b2..f431e1fe84a19 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/SignedIdentifiersWrapper.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/SignedIdentifiersWrapper.java @@ -16,7 +16,7 @@ */ @JacksonXmlRootElement(localName = "SignedIdentifiers") public final class SignedIdentifiersWrapper { - @JacksonXmlProperty(localName = "SignedIdentifier") + @JacksonXmlProperty(localName = "SignedIdentifiers") private final List signedIdentifiers; /** diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/AccessPolicy.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/AccessPolicy.java index 8b33f24bf5714..04ded069ff534 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/AccessPolicy.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/AccessPolicy.java @@ -4,6 +4,7 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -12,6 +13,7 @@ * An Access policy. */ @JacksonXmlRootElement(localName = "AccessPolicy") +@Fluent public final class AccessPolicy { /* * the date-time the policy is active diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/AppendBlobAppendBlockFromUrlHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/AppendBlobAppendBlockFromUrlHeaders.java index 8273338cb6676..8dcea49cd76c6 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/AppendBlobAppendBlockFromUrlHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/AppendBlobAppendBlockFromUrlHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.azure.core.implementation.util.ImplUtils; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -14,6 +15,7 @@ * Defines headers for AppendBlockFromUrl operation. */ @JacksonXmlRootElement(localName = "AppendBlob-AppendBlockFromUrl-Headers") +@Fluent public final class AppendBlobAppendBlockFromUrlHeaders { /* * The ETag contains a value that you can use to perform operations diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/AppendBlobAppendBlockHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/AppendBlobAppendBlockHeaders.java index 8fe788378e589..a12cefa924e68 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/AppendBlobAppendBlockHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/AppendBlobAppendBlockHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.azure.core.implementation.util.ImplUtils; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -14,6 +15,7 @@ * Defines headers for AppendBlock operation. */ @JacksonXmlRootElement(localName = "AppendBlob-AppendBlock-Headers") +@Fluent public final class AppendBlobAppendBlockHeaders { /* * The ETag contains a value that you can use to perform operations diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/AppendBlobCreateHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/AppendBlobCreateHeaders.java index 45fd447bde387..c2e5a3e0929ed 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/AppendBlobCreateHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/AppendBlobCreateHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.azure.core.implementation.util.ImplUtils; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -14,6 +15,7 @@ * Defines headers for Create operation. */ @JacksonXmlRootElement(localName = "AppendBlob-Create-Headers") +@Fluent public final class AppendBlobCreateHeaders { /* * The ETag contains a value that you can use to perform operations diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/AppendPositionAccessConditions.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/AppendPositionAccessConditions.java index 5894e08f86e36..e63fabf516af6 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/AppendPositionAccessConditions.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/AppendPositionAccessConditions.java @@ -4,6 +4,7 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -12,6 +13,7 @@ * AppendBlobs_appendBlock, AppendBlobs_appendBlockFromUrl. */ @JacksonXmlRootElement(localName = "append-position-access-conditions") +@Fluent public final class AppendPositionAccessConditions { /* * Optional conditional header. The max length in bytes permitted for the diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobAbortCopyFromURLHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobAbortCopyFromURLHeaders.java index e439f5b8b0892..c27f9fcac790f 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobAbortCopyFromURLHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobAbortCopyFromURLHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for AbortCopyFromURL operation. */ @JacksonXmlRootElement(localName = "Blob-AbortCopyFromURL-Headers") +@Fluent public final class BlobAbortCopyFromURLHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobAcquireLeaseHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobAcquireLeaseHeaders.java index 5bf6ef2560117..d4649062bc60c 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobAcquireLeaseHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobAcquireLeaseHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for AcquireLease operation. */ @JacksonXmlRootElement(localName = "Blob-AcquireLease-Headers") +@Fluent public final class BlobAcquireLeaseHeaders { /* * The ETag contains a value that you can use to perform operations diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobBreakLeaseHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobBreakLeaseHeaders.java index b136802ce69ad..504b7201befe6 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobBreakLeaseHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobBreakLeaseHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for BreakLease operation. */ @JacksonXmlRootElement(localName = "Blob-BreakLease-Headers") +@Fluent public final class BlobBreakLeaseHeaders { /* * The ETag contains a value that you can use to perform operations diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobChangeLeaseHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobChangeLeaseHeaders.java index 1c3010861eaf0..67d6971d9ff32 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobChangeLeaseHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobChangeLeaseHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for ChangeLease operation. */ @JacksonXmlRootElement(localName = "Blob-ChangeLease-Headers") +@Fluent public final class BlobChangeLeaseHeaders { /* * The ETag contains a value that you can use to perform operations diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobCopyFromURLHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobCopyFromURLHeaders.java index 2568e1c566bcf..140b771f8cd64 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobCopyFromURLHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobCopyFromURLHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for CopyFromURL operation. */ @JacksonXmlRootElement(localName = "Blob-CopyFromURL-Headers") +@Fluent public final class BlobCopyFromURLHeaders { /* * The ETag contains a value that you can use to perform operations diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobCreateSnapshotHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobCreateSnapshotHeaders.java index f185a465e483e..e27c4fde4964a 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobCreateSnapshotHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobCreateSnapshotHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for CreateSnapshot operation. */ @JacksonXmlRootElement(localName = "Blob-CreateSnapshot-Headers") +@Fluent public final class BlobCreateSnapshotHeaders { /* * Uniquely identifies the snapshot and indicates the snapshot version. It diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobDeleteHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobDeleteHeaders.java index 7aeac53bc5a33..95e6289c3e40b 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobDeleteHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobDeleteHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for Delete operation. */ @JacksonXmlRootElement(localName = "Blob-Delete-Headers") +@Fluent public final class BlobDeleteHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobDownloadHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobDownloadHeaders.java index aa56c2e6683c4..4e9e2997ebab0 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobDownloadHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobDownloadHeaders.java @@ -4,8 +4,9 @@ package com.azure.storage.blob.models; -import com.azure.core.annotations.HeaderCollection; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; +import com.azure.core.implementation.annotation.HeaderCollection; import com.azure.core.implementation.util.ImplUtils; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -16,6 +17,7 @@ * Defines headers for Download operation. */ @JacksonXmlRootElement(localName = "Blob-Download-Headers") +@Fluent public final class BlobDownloadHeaders { /* * Returns the date and time the container was last modified. Any operation diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobFlatListSegment.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobFlatListSegment.java index 97f8e48a9c832..ac1f703d1cd7c 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobFlatListSegment.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobFlatListSegment.java @@ -4,6 +4,7 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.util.ArrayList; @@ -13,6 +14,7 @@ * The BlobFlatListSegment model. */ @JacksonXmlRootElement(localName = "Blobs") +@Fluent public final class BlobFlatListSegment { /* * The blobItems property. diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobGetAccountInfoHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobGetAccountInfoHeaders.java index 81c8b54b46615..21243aaac7325 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobGetAccountInfoHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobGetAccountInfoHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for GetAccountInfo operation. */ @JacksonXmlRootElement(localName = "Blob-GetAccountInfo-Headers") +@Fluent public final class BlobGetAccountInfoHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobGetPropertiesHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobGetPropertiesHeaders.java index cb1d9e3ba1762..728ae5fd9e1e2 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobGetPropertiesHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobGetPropertiesHeaders.java @@ -4,8 +4,9 @@ package com.azure.storage.blob.models; -import com.azure.core.annotations.HeaderCollection; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; +import com.azure.core.implementation.annotation.HeaderCollection; import com.azure.core.implementation.util.ImplUtils; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -16,6 +17,7 @@ * Defines headers for GetProperties operation. */ @JacksonXmlRootElement(localName = "Blob-GetProperties-Headers") +@Fluent public final class BlobGetPropertiesHeaders { /* * Returns the date and time the blob was last modified. Any operation that diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobHTTPHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobHTTPHeaders.java index aafbd1eb56e5e..f25f4e566e6b8 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobHTTPHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobHTTPHeaders.java @@ -4,6 +4,7 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.azure.core.implementation.util.ImplUtils; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -12,6 +13,7 @@ * Additional parameters for a set of operations. */ @JacksonXmlRootElement(localName = "blob-HTTP-headers") +@Fluent public final class BlobHTTPHeaders { /* * Optional. Sets the blob's cache control. If specified, this property is diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobHierarchyListSegment.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobHierarchyListSegment.java index a70c2d2122f04..d90e89ab602f3 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobHierarchyListSegment.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobHierarchyListSegment.java @@ -4,8 +4,8 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.util.ArrayList; import java.util.List; @@ -14,7 +14,7 @@ * The BlobHierarchyListSegment model. */ @JacksonXmlRootElement(localName = "Blobs") -@JsonDeserialize(using = CustomHierarchicalListingDeserializer.class) +@Fluent public final class BlobHierarchyListSegment { /* * The blobPrefixes property. diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobMetadata.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobMetadata.java index 5753ff479dbfb..30eed457954bb 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobMetadata.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobMetadata.java @@ -4,6 +4,7 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -13,6 +14,7 @@ * The BlobMetadata model. */ @JacksonXmlRootElement(localName = "Metadata") +@Fluent public final class BlobMetadata { /* * Unmatched properties from the message are deserialized this collection diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobPrefix.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobPrefix.java index 6507aaecfd380..55afd0bc25491 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobPrefix.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobPrefix.java @@ -4,6 +4,7 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * The BlobPrefix model. */ @JacksonXmlRootElement(localName = "BlobPrefix") +@Fluent public final class BlobPrefix { /* * The name property. diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobProperties.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobProperties.java index a297fe40e0432..d5bad7b9996e5 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobProperties.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobProperties.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.azure.core.implementation.util.ImplUtils; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -14,6 +15,7 @@ * Properties of a blob. */ @JacksonXmlRootElement(localName = "Properties") +@Fluent public final class BlobProperties { /* * The creationTime property. diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobReleaseLeaseHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobReleaseLeaseHeaders.java index 661e9a24db979..f503b9ab6d309 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobReleaseLeaseHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobReleaseLeaseHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for ReleaseLease operation. */ @JacksonXmlRootElement(localName = "Blob-ReleaseLease-Headers") +@Fluent public final class BlobReleaseLeaseHeaders { /* * The ETag contains a value that you can use to perform operations diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobRenewLeaseHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobRenewLeaseHeaders.java index 2ee66b3adb36b..863157cf8a427 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobRenewLeaseHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobRenewLeaseHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for RenewLease operation. */ @JacksonXmlRootElement(localName = "Blob-RenewLease-Headers") +@Fluent public final class BlobRenewLeaseHeaders { /* * The ETag contains a value that you can use to perform operations diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobSetHTTPHeadersHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobSetHTTPHeadersHeaders.java index 09111d5ae3e17..ed539d644bc1a 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobSetHTTPHeadersHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobSetHTTPHeadersHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for SetHTTPHeaders operation. */ @JacksonXmlRootElement(localName = "Blob-SetHTTPHeaders-Headers") +@Fluent public final class BlobSetHTTPHeadersHeaders { /* * The ETag contains a value that you can use to perform operations diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobSetMetadataHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobSetMetadataHeaders.java index b831d8446cd1a..5b3898194287e 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobSetMetadataHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobSetMetadataHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for SetMetadata operation. */ @JacksonXmlRootElement(localName = "Blob-SetMetadata-Headers") +@Fluent public final class BlobSetMetadataHeaders { /* * The ETag contains a value that you can use to perform operations diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobSetTierHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobSetTierHeaders.java index d2dd04c235a76..372b1a09ebc00 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobSetTierHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobSetTierHeaders.java @@ -4,6 +4,7 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * Defines headers for SetTier operation. */ @JacksonXmlRootElement(localName = "Blob-SetTier-Headers") +@Fluent public final class BlobSetTierHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobStartCopyFromURLHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobStartCopyFromURLHeaders.java index c0059d598cceb..a6b195a6e6dcc 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobStartCopyFromURLHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobStartCopyFromURLHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for StartCopyFromURL operation. */ @JacksonXmlRootElement(localName = "Blob-StartCopyFromURL-Headers") +@Fluent public final class BlobStartCopyFromURLHeaders { /* * The ETag contains a value that you can use to perform operations diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobUndeleteHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobUndeleteHeaders.java index 3123885e3af1f..cd1ea6a55d13d 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobUndeleteHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobUndeleteHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for Undelete operation. */ @JacksonXmlRootElement(localName = "Blob-Undelete-Headers") +@Fluent public final class BlobUndeleteHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/Block.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/Block.java index 8fbfcaa8a7abe..5cfa164c8c854 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/Block.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/Block.java @@ -4,6 +4,7 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -12,6 +13,7 @@ * size. */ @JacksonXmlRootElement(localName = "Block") +@Fluent public final class Block { /* * The base64 encoded block ID. diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlockBlobCommitBlockListHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlockBlobCommitBlockListHeaders.java index a2605e19cf430..6bec949d71804 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlockBlobCommitBlockListHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlockBlobCommitBlockListHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.azure.core.implementation.util.ImplUtils; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -14,6 +15,7 @@ * Defines headers for CommitBlockList operation. */ @JacksonXmlRootElement(localName = "BlockBlob-CommitBlockList-Headers") +@Fluent public final class BlockBlobCommitBlockListHeaders { /* * The ETag contains a value that you can use to perform operations diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlockBlobGetBlockListHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlockBlobGetBlockListHeaders.java index 26d77f85abadf..fa50d846ebefa 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlockBlobGetBlockListHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlockBlobGetBlockListHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for GetBlockList operation. */ @JacksonXmlRootElement(localName = "BlockBlob-GetBlockList-Headers") +@Fluent public final class BlockBlobGetBlockListHeaders { /* * Returns the date and time the container was last modified. Any operation diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlockBlobStageBlockFromURLHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlockBlobStageBlockFromURLHeaders.java index 1b434c919342f..88dd3c6346edd 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlockBlobStageBlockFromURLHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlockBlobStageBlockFromURLHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.azure.core.implementation.util.ImplUtils; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -14,6 +15,7 @@ * Defines headers for StageBlockFromURL operation. */ @JacksonXmlRootElement(localName = "BlockBlob-StageBlockFromURL-Headers") +@Fluent public final class BlockBlobStageBlockFromURLHeaders { /* * If the blob has an MD5 hash and this operation is to read the full blob, diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlockBlobStageBlockHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlockBlobStageBlockHeaders.java index 40108ad24ec2a..56ffdfe937001 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlockBlobStageBlockHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlockBlobStageBlockHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.azure.core.implementation.util.ImplUtils; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -14,6 +15,7 @@ * Defines headers for StageBlock operation. */ @JacksonXmlRootElement(localName = "BlockBlob-StageBlock-Headers") +@Fluent public final class BlockBlobStageBlockHeaders { /* * If the blob has an MD5 hash and this operation is to read the full blob, diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlockBlobUploadHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlockBlobUploadHeaders.java index e5430e100e6ea..76c59b2f74d94 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlockBlobUploadHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlockBlobUploadHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.azure.core.implementation.util.ImplUtils; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -14,6 +15,7 @@ * Defines headers for Upload operation. */ @JacksonXmlRootElement(localName = "BlockBlob-Upload-Headers") +@Fluent public final class BlockBlobUploadHeaders { /* * The ETag contains a value that you can use to perform operations diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlockList.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlockList.java index 70a0fb8d312ef..dfa4deadeb89c 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlockList.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlockList.java @@ -4,6 +4,7 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; @@ -15,6 +16,7 @@ * The BlockList model. */ @JacksonXmlRootElement(localName = "BlockList") +@Fluent public final class BlockList { private static final class CommittedBlocksWrapper { @JacksonXmlProperty(localName = "Block") diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlockLookupList.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlockLookupList.java index 9cc63338a8996..40bb5d346e004 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlockLookupList.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlockLookupList.java @@ -4,6 +4,7 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.util.ArrayList; @@ -13,6 +14,7 @@ * The BlockLookupList model. */ @JacksonXmlRootElement(localName = "BlockList") +@Fluent public final class BlockLookupList { /* * The committed property. diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ClearRange.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ClearRange.java index cb8d7a208ab3a..e607faf87b058 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ClearRange.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ClearRange.java @@ -4,6 +4,7 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * The ClearRange model. */ @JacksonXmlRootElement(localName = "ClearRange") +@Fluent public final class ClearRange { /* * The start property. diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerAcquireLeaseHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerAcquireLeaseHeaders.java index 0ba172f04e33a..bd6d0580bdcfb 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerAcquireLeaseHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerAcquireLeaseHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for AcquireLease operation. */ @JacksonXmlRootElement(localName = "Container-AcquireLease-Headers") +@Fluent public final class ContainerAcquireLeaseHeaders { /* * The ETag contains a value that you can use to perform operations diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerBreakLeaseHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerBreakLeaseHeaders.java index 98a1106ccc6ef..4df2a5f3ddef2 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerBreakLeaseHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerBreakLeaseHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for BreakLease operation. */ @JacksonXmlRootElement(localName = "Container-BreakLease-Headers") +@Fluent public final class ContainerBreakLeaseHeaders { /* * The ETag contains a value that you can use to perform operations diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerChangeLeaseHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerChangeLeaseHeaders.java index 880214fc46b52..8c5371a5121f7 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerChangeLeaseHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerChangeLeaseHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for ChangeLease operation. */ @JacksonXmlRootElement(localName = "Container-ChangeLease-Headers") +@Fluent public final class ContainerChangeLeaseHeaders { /* * The ETag contains a value that you can use to perform operations diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerCreateHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerCreateHeaders.java index 280734c615016..9a22e560ca72c 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerCreateHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerCreateHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for Create operation. */ @JacksonXmlRootElement(localName = "Container-Create-Headers") +@Fluent public final class ContainerCreateHeaders { /* * The ETag contains a value that you can use to perform operations diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerDeleteHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerDeleteHeaders.java index 52f2623a635d5..64af976e03679 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerDeleteHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerDeleteHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for Delete operation. */ @JacksonXmlRootElement(localName = "Container-Delete-Headers") +@Fluent public final class ContainerDeleteHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerGetAccessPolicyHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerGetAccessPolicyHeaders.java index 4905b3c2949fe..a1a76b2f57ba5 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerGetAccessPolicyHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerGetAccessPolicyHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for GetAccessPolicy operation. */ @JacksonXmlRootElement(localName = "Container-GetAccessPolicy-Headers") +@Fluent public final class ContainerGetAccessPolicyHeaders { /* * Indicated whether data in the container may be accessed publicly and the diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerGetAccountInfoHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerGetAccountInfoHeaders.java index c82baa2c1a6b7..692c4a71fc522 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerGetAccountInfoHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerGetAccountInfoHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for GetAccountInfo operation. */ @JacksonXmlRootElement(localName = "Container-GetAccountInfo-Headers") +@Fluent public final class ContainerGetAccountInfoHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerGetPropertiesHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerGetPropertiesHeaders.java index b37286c1b7af3..df2d12bbcdb6e 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerGetPropertiesHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerGetPropertiesHeaders.java @@ -4,8 +4,9 @@ package com.azure.storage.blob.models; -import com.azure.core.annotations.HeaderCollection; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; +import com.azure.core.implementation.annotation.HeaderCollection; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -15,6 +16,7 @@ * Defines headers for GetProperties operation. */ @JacksonXmlRootElement(localName = "Container-GetProperties-Headers") +@Fluent public final class ContainerGetPropertiesHeaders { /* * The metadata property. diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerItem.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerItem.java index a334568661eb1..543085f349c81 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerItem.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerItem.java @@ -4,6 +4,7 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.util.Map; @@ -12,6 +13,7 @@ * An Azure Storage container. */ @JacksonXmlRootElement(localName = "Container") +@Fluent public final class ContainerItem { /* * The name property. diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerListBlobFlatSegmentHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerListBlobFlatSegmentHeaders.java index 311c0c6ca66bf..ef1252a5a8d4c 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerListBlobFlatSegmentHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerListBlobFlatSegmentHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for ListBlobFlatSegment operation. */ @JacksonXmlRootElement(localName = "Container-ListBlobFlatSegment-Headers") +@Fluent public final class ContainerListBlobFlatSegmentHeaders { /* * The media type of the body of the response. For List Blobs this is diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerListBlobHierarchySegmentHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerListBlobHierarchySegmentHeaders.java index 7456e14d89809..d1a671cf75501 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerListBlobHierarchySegmentHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerListBlobHierarchySegmentHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for ListBlobHierarchySegment operation. */ @JacksonXmlRootElement(localName = "Container-ListBlobHierarchySegment-Headers") +@Fluent public final class ContainerListBlobHierarchySegmentHeaders { /* * The media type of the body of the response. For List Blobs this is diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerProperties.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerProperties.java index b4844ac52dcfb..f159a57f2cd5c 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerProperties.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerProperties.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Properties of a container. */ @JacksonXmlRootElement(localName = "ContainerProperties") +@Fluent public final class ContainerProperties { /* * The lastModified property. diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerReleaseLeaseHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerReleaseLeaseHeaders.java index b437d814e16ca..7a8766ab2424b 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerReleaseLeaseHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerReleaseLeaseHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for ReleaseLease operation. */ @JacksonXmlRootElement(localName = "Container-ReleaseLease-Headers") +@Fluent public final class ContainerReleaseLeaseHeaders { /* * The ETag contains a value that you can use to perform operations diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerRenewLeaseHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerRenewLeaseHeaders.java index e9a03210ae1a3..a192e95a96c8e 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerRenewLeaseHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerRenewLeaseHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for RenewLease operation. */ @JacksonXmlRootElement(localName = "Container-RenewLease-Headers") +@Fluent public final class ContainerRenewLeaseHeaders { /* * The ETag contains a value that you can use to perform operations diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerSetAccessPolicyHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerSetAccessPolicyHeaders.java index a91ceed6d34d1..763e752918002 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerSetAccessPolicyHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerSetAccessPolicyHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for SetAccessPolicy operation. */ @JacksonXmlRootElement(localName = "Container-SetAccessPolicy-Headers") +@Fluent public final class ContainerSetAccessPolicyHeaders { /* * The ETag contains a value that you can use to perform operations diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerSetMetadataHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerSetMetadataHeaders.java index 082886b7c0b54..e685322b83ffa 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerSetMetadataHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ContainerSetMetadataHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for SetMetadata operation. */ @JacksonXmlRootElement(localName = "Container-SetMetadata-Headers") +@Fluent public final class ContainerSetMetadataHeaders { /* * The ETag contains a value that you can use to perform operations diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/CorsRule.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/CorsRule.java index fa9035b072c6c..e111fbb62e308 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/CorsRule.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/CorsRule.java @@ -4,6 +4,7 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -15,6 +16,7 @@ * one domain (the origin domain) to call APIs in another domain. */ @JacksonXmlRootElement(localName = "CorsRule") +@Fluent public final class CorsRule { /* * The origin domains that are permitted to make a request against the diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/GeoReplication.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/GeoReplication.java index 90cf41b12f07f..d583130cc13a9 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/GeoReplication.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/GeoReplication.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Geo-Replication information for the Secondary Storage Service. */ @JacksonXmlRootElement(localName = "GeoReplication") +@Fluent public final class GeoReplication { /* * The status of the secondary location. Possible values include: 'live', diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/KeyInfo.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/KeyInfo.java index d1aa23bbcef7c..6c742e4ed7860 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/KeyInfo.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/KeyInfo.java @@ -4,6 +4,7 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * Key information. */ @JacksonXmlRootElement(localName = "KeyInfo") +@Fluent public final class KeyInfo { /* * The date-time the key is active in ISO 8601 UTC time diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/LeaseAccessConditions.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/LeaseAccessConditions.java index eae367a636e25..9a43064e549f5 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/LeaseAccessConditions.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/LeaseAccessConditions.java @@ -4,6 +4,7 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * Additional parameters for a set of operations. */ @JacksonXmlRootElement(localName = "lease-access-conditions") +@Fluent public final class LeaseAccessConditions { /* * If specified, the operation only succeeds if the resource's lease is diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ListBlobsFlatSegmentResponse.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ListBlobsFlatSegmentResponse.java index 1807bc8efe364..593688ccc3e11 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ListBlobsFlatSegmentResponse.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ListBlobsFlatSegmentResponse.java @@ -4,6 +4,7 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -12,6 +13,7 @@ * An enumeration of blobs. */ @JacksonXmlRootElement(localName = "EnumerationResults") +@Fluent public final class ListBlobsFlatSegmentResponse { /* * The serviceEndpoint property. diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ListBlobsHierarchySegmentResponse.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ListBlobsHierarchySegmentResponse.java index f79c285a10796..51aee28565674 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ListBlobsHierarchySegmentResponse.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ListBlobsHierarchySegmentResponse.java @@ -4,6 +4,7 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -12,6 +13,7 @@ * An enumeration of blobs. */ @JacksonXmlRootElement(localName = "EnumerationResults") +@Fluent public final class ListBlobsHierarchySegmentResponse { /* * The serviceEndpoint property. diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ListContainersSegmentResponse.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ListContainersSegmentResponse.java index deafc07a94435..97f342484a8fc 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ListContainersSegmentResponse.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ListContainersSegmentResponse.java @@ -4,6 +4,7 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; @@ -15,6 +16,7 @@ * An enumeration of containers. */ @JacksonXmlRootElement(localName = "EnumerationResults") +@Fluent public final class ListContainersSegmentResponse { /* * The serviceEndpoint property. diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/Logging.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/Logging.java index e86ad32a0ae74..9aa3f4cce40b3 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/Logging.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/Logging.java @@ -4,6 +4,7 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * Azure Analytics Logging settings. */ @JacksonXmlRootElement(localName = "Logging") +@Fluent public final class Logging { /* * The version of Storage Analytics to configure. diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/Metrics.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/Metrics.java index c812d6a86a533..ee8ad19b28563 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/Metrics.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/Metrics.java @@ -4,6 +4,7 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -12,6 +13,7 @@ * for blobs. */ @JacksonXmlRootElement(localName = "Metrics") +@Fluent public final class Metrics { /* * The version of Storage Analytics to configure. diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ModifiedAccessConditions.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ModifiedAccessConditions.java index 3636dfd4c290c..01e9de89ae16a 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ModifiedAccessConditions.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ModifiedAccessConditions.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Additional parameters for a set of operations. */ @JacksonXmlRootElement(localName = "modified-access-conditions") +@Fluent public final class ModifiedAccessConditions { /* * Specify this header value to operate only on a blob if it has been diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobClearPagesHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobClearPagesHeaders.java index 45f30cefd53a1..543c829bf2718 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobClearPagesHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobClearPagesHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.azure.core.implementation.util.ImplUtils; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -14,6 +15,7 @@ * Defines headers for ClearPages operation. */ @JacksonXmlRootElement(localName = "PageBlob-ClearPages-Headers") +@Fluent public final class PageBlobClearPagesHeaders { /* * The ETag contains a value that you can use to perform operations diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobCopyIncrementalHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobCopyIncrementalHeaders.java index 3a1ea5cd5f9d7..7e9aa95c1ff37 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobCopyIncrementalHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobCopyIncrementalHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for CopyIncremental operation. */ @JacksonXmlRootElement(localName = "PageBlob-CopyIncremental-Headers") +@Fluent public final class PageBlobCopyIncrementalHeaders { /* * The ETag contains a value that you can use to perform operations diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobCreateHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobCreateHeaders.java index 215c6f4c934aa..6c4192fe4806d 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobCreateHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobCreateHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.azure.core.implementation.util.ImplUtils; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -14,6 +15,7 @@ * Defines headers for Create operation. */ @JacksonXmlRootElement(localName = "PageBlob-Create-Headers") +@Fluent public final class PageBlobCreateHeaders { /* * The ETag contains a value that you can use to perform operations diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobGetPageRangesDiffHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobGetPageRangesDiffHeaders.java index 5f75cf82af768..c1d14635bf44f 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobGetPageRangesDiffHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobGetPageRangesDiffHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for GetPageRangesDiff operation. */ @JacksonXmlRootElement(localName = "PageBlob-GetPageRangesDiff-Headers") +@Fluent public final class PageBlobGetPageRangesDiffHeaders { /* * Returns the date and time the container was last modified. Any operation diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobGetPageRangesHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobGetPageRangesHeaders.java index a9004d8dd2c91..32b37ef1452c0 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobGetPageRangesHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobGetPageRangesHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for GetPageRanges operation. */ @JacksonXmlRootElement(localName = "PageBlob-GetPageRanges-Headers") +@Fluent public final class PageBlobGetPageRangesHeaders { /* * Returns the date and time the container was last modified. Any operation diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobResizeHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobResizeHeaders.java index f9396b66835c3..e03c8720d2b67 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobResizeHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobResizeHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for Resize operation. */ @JacksonXmlRootElement(localName = "PageBlob-Resize-Headers") +@Fluent public final class PageBlobResizeHeaders { /* * The ETag contains a value that you can use to perform operations diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobUpdateSequenceNumberHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobUpdateSequenceNumberHeaders.java index 317c57bb35cea..5f606b24c2622 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobUpdateSequenceNumberHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobUpdateSequenceNumberHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for UpdateSequenceNumber operation. */ @JacksonXmlRootElement(localName = "PageBlob-UpdateSequenceNumber-Headers") +@Fluent public final class PageBlobUpdateSequenceNumberHeaders { /* * The ETag contains a value that you can use to perform operations diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobUploadPagesFromURLHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobUploadPagesFromURLHeaders.java index ad21b582b509e..cebeb20842e37 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobUploadPagesFromURLHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobUploadPagesFromURLHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.azure.core.implementation.util.ImplUtils; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -14,6 +15,7 @@ * Defines headers for UploadPagesFromURL operation. */ @JacksonXmlRootElement(localName = "PageBlob-UploadPagesFromURL-Headers") +@Fluent public final class PageBlobUploadPagesFromURLHeaders { /* * The ETag contains a value that you can use to perform operations diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobUploadPagesHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobUploadPagesHeaders.java index 29cf41bae0b8e..7dd8eb12ae720 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobUploadPagesHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageBlobUploadPagesHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.azure.core.implementation.util.ImplUtils; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -14,6 +15,7 @@ * Defines headers for UploadPages operation. */ @JacksonXmlRootElement(localName = "PageBlob-UploadPages-Headers") +@Fluent public final class PageBlobUploadPagesHeaders { /* * The ETag contains a value that you can use to perform operations diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageList.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageList.java index cf921ab92646b..b981bdf2f6edb 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageList.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageList.java @@ -4,6 +4,7 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.util.ArrayList; @@ -13,6 +14,7 @@ * the list of pages. */ @JacksonXmlRootElement(localName = "PageList") +@Fluent public final class PageList { /* * The pageRange property. diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageRange.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageRange.java index 5ce78ebfb0db8..53a76779cd4d4 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageRange.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/PageRange.java @@ -4,6 +4,7 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * The PageRange model. */ @JacksonXmlRootElement(localName = "PageRange") +@Fluent public final class PageRange { /* * The start property. diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/RetentionPolicy.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/RetentionPolicy.java index d6285c64af18f..7877f6dd0bd76 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/RetentionPolicy.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/RetentionPolicy.java @@ -4,6 +4,7 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -12,6 +13,7 @@ * persist. */ @JacksonXmlRootElement(localName = "RetentionPolicy") +@Fluent public final class RetentionPolicy { /* * Indicates whether a retention policy is enabled for the storage service diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/SequenceNumberAccessConditions.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/SequenceNumberAccessConditions.java index df0399ff59123..c211020aeb245 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/SequenceNumberAccessConditions.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/SequenceNumberAccessConditions.java @@ -4,6 +4,7 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -12,6 +13,7 @@ * PageBlobs_uploadPages, PageBlobs_clearPages, PageBlobs_uploadPagesFromURL. */ @JacksonXmlRootElement(localName = "sequence-number-access-conditions") +@Fluent public final class SequenceNumberAccessConditions { /* * Specify this header value to operate only on a blob if it has a sequence diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ServiceGetAccountInfoHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ServiceGetAccountInfoHeaders.java index b0c6820cf0848..88fa50830518e 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ServiceGetAccountInfoHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ServiceGetAccountInfoHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for GetAccountInfo operation. */ @JacksonXmlRootElement(localName = "Service-GetAccountInfo-Headers") +@Fluent public final class ServiceGetAccountInfoHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ServiceGetPropertiesHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ServiceGetPropertiesHeaders.java index 3126a5153421e..3b5b06ab3259a 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ServiceGetPropertiesHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ServiceGetPropertiesHeaders.java @@ -4,6 +4,7 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * Defines headers for GetProperties operation. */ @JacksonXmlRootElement(localName = "Service-GetProperties-Headers") +@Fluent public final class ServiceGetPropertiesHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ServiceGetStatisticsHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ServiceGetStatisticsHeaders.java index 34fcda3653a60..55dda9cc8ddb6 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ServiceGetStatisticsHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ServiceGetStatisticsHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for GetStatistics operation. */ @JacksonXmlRootElement(localName = "Service-GetStatistics-Headers") +@Fluent public final class ServiceGetStatisticsHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ServiceGetUserDelegationKeyHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ServiceGetUserDelegationKeyHeaders.java index 9c685c2906102..4a74086587afa 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ServiceGetUserDelegationKeyHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ServiceGetUserDelegationKeyHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for GetUserDelegationKey operation. */ @JacksonXmlRootElement(localName = "Service-GetUserDelegationKey-Headers") +@Fluent public final class ServiceGetUserDelegationKeyHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ServiceListContainersSegmentHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ServiceListContainersSegmentHeaders.java index d22b9f1febc4f..94908506ede78 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ServiceListContainersSegmentHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ServiceListContainersSegmentHeaders.java @@ -4,6 +4,7 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * Defines headers for ListContainersSegment operation. */ @JacksonXmlRootElement(localName = "Service-ListContainersSegment-Headers") +@Fluent public final class ServiceListContainersSegmentHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ServiceSetPropertiesHeaders.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ServiceSetPropertiesHeaders.java index 065e595244fc3..df15cc7664002 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/ServiceSetPropertiesHeaders.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/ServiceSetPropertiesHeaders.java @@ -4,6 +4,7 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * Defines headers for SetProperties operation. */ @JacksonXmlRootElement(localName = "Service-SetProperties-Headers") +@Fluent public final class ServiceSetPropertiesHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/SignedIdentifier.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/SignedIdentifier.java index 417f49492e51a..63e3aea5e584b 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/SignedIdentifier.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/SignedIdentifier.java @@ -4,6 +4,7 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * signed identifier. */ @JacksonXmlRootElement(localName = "SignedIdentifier") +@Fluent public final class SignedIdentifier { /* * a unique id diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/SourceModifiedAccessConditions.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/SourceModifiedAccessConditions.java index 84b179bb01812..9874a3b9557ed 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/SourceModifiedAccessConditions.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/SourceModifiedAccessConditions.java @@ -5,6 +5,7 @@ package com.azure.storage.blob.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Additional parameters for a set of operations. */ @JacksonXmlRootElement(localName = "source-modified-access-conditions") +@Fluent public final class SourceModifiedAccessConditions { /* * Specify this header value to operate only on a blob if it has been diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/StaticWebsite.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/StaticWebsite.java index 45971febb06e2..91fffc8ba4bc8 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/StaticWebsite.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/StaticWebsite.java @@ -4,6 +4,7 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * The properties that enable an account to host a static website. */ @JacksonXmlRootElement(localName = "StaticWebsite") +@Fluent public final class StaticWebsite { /* * Indicates whether this account is hosting a static website diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/StorageError.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/StorageError.java index 55c96be21c801..2f8f01f4f6f9d 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/StorageError.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/StorageError.java @@ -4,6 +4,7 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * The StorageError model. */ @JacksonXmlRootElement(localName = "StorageError") +@Fluent public final class StorageError { /* * The code property. diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/StorageServiceProperties.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/StorageServiceProperties.java index 79e072ba2b059..a83c072fcce9f 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/StorageServiceProperties.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/StorageServiceProperties.java @@ -4,6 +4,7 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; @@ -15,6 +16,7 @@ * Storage Service Properties. */ @JacksonXmlRootElement(localName = "StorageServiceProperties") +@Fluent public final class StorageServiceProperties { /* * The logging property. diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/StorageServiceStats.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/StorageServiceStats.java index 5eb67c3230645..04dd8dfc94dd6 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/StorageServiceStats.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/StorageServiceStats.java @@ -4,6 +4,7 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * Stats for the storage service. */ @JacksonXmlRootElement(localName = "StorageServiceStats") +@Fluent public final class StorageServiceStats { /* * The geoReplication property. diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/UserDelegationKey.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/UserDelegationKey.java index d267df92d7c29..7598fd90340d5 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/UserDelegationKey.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/UserDelegationKey.java @@ -4,6 +4,7 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -12,6 +13,7 @@ * A user delegation key. */ @JacksonXmlRootElement(localName = "UserDelegationKey") +@Fluent public final class UserDelegationKey { /* * The Azure Active Directory object ID in GUID format. diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/package-info.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/package-info.java index a078397789b87..653e8a46d1d67 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/package-info.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/package-info.java @@ -3,6 +3,6 @@ // Code generated by Microsoft (R) AutoRest Code Generator. /** - * Package containing the data models for AzureBlobStorage. + * This package contains the data models for AzureBlobStorage. */ package com.azure.storage.blob.models; 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..07a401015b89c 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 @@ -6,10 +6,12 @@ import com.azure.core.http.HttpPipeline; import com.azure.core.implementation.RestProxy; +import com.azure.core.implementation.annotation.ServiceClientBuilder; /** - * A appendBlobClientBuilder for creating a new instance of the AzureFileStorage type. + * A builder for creating a new instance of the AzureFileStorage type. */ +@ServiceClientBuilder(serviceClients = AzureFileStorageImpl.class) public final class AzureFileStorageBuilder { /* * Specifies the version of the operation to use for this request. diff --git a/storage/client/file/src/main/java/com/azure/storage/file/implementation/AzureFileStorageImpl.java b/storage/client/file/src/main/java/com/azure/storage/file/implementation/AzureFileStorageImpl.java index ec39450873537..8524d71ef6e2f 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/implementation/AzureFileStorageImpl.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/implementation/AzureFileStorageImpl.java @@ -4,14 +4,13 @@ package com.azure.storage.file.implementation; -import com.azure.core.ServiceClient; import com.azure.core.http.HttpPipeline; import com.azure.core.implementation.RestProxy; /** * Initializes a new instance of the AzureFileStorage type. */ -public final class AzureFileStorageImpl extends ServiceClient { +public final class AzureFileStorageImpl { /** * Specifies the version of the operation to use for this request. */ @@ -62,6 +61,20 @@ AzureFileStorageImpl url(String url) { return this; } + /** + * The HTTP pipeline to send requests through. + */ + private HttpPipeline httpPipeline; + + /** + * Gets The HTTP pipeline to send requests through. + * + * @return the httpPipeline value. + */ + public HttpPipeline httpPipeline() { + return this.httpPipeline; + } + /** * The ServicesImpl object to access its operations. */ @@ -131,7 +144,7 @@ public AzureFileStorageImpl() { * @param httpPipeline The HTTP pipeline to send requests through. */ public AzureFileStorageImpl(HttpPipeline httpPipeline) { - super(httpPipeline); + this.httpPipeline = httpPipeline; this.services = new ServicesImpl(this); this.shares = new SharesImpl(this); this.directorys = new DirectorysImpl(this); 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..a7a40bc0007e6 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 @@ -4,17 +4,19 @@ package com.azure.storage.file.implementation; -import com.azure.core.annotations.DELETE; -import com.azure.core.annotations.ExpectedResponses; -import com.azure.core.annotations.GET; -import com.azure.core.annotations.HeaderParam; -import com.azure.core.annotations.Host; -import com.azure.core.annotations.HostParam; -import com.azure.core.annotations.PUT; -import com.azure.core.annotations.QueryParam; -import com.azure.core.annotations.Service; -import com.azure.core.annotations.UnexpectedResponseExceptionType; import com.azure.core.implementation.RestProxy; +import com.azure.core.implementation.annotation.Delete; +import com.azure.core.implementation.annotation.ExpectedResponses; +import com.azure.core.implementation.annotation.Get; +import com.azure.core.implementation.annotation.HeaderParam; +import com.azure.core.implementation.annotation.Host; +import com.azure.core.implementation.annotation.HostParam; +import com.azure.core.implementation.annotation.Put; +import com.azure.core.implementation.annotation.QueryParam; +import com.azure.core.implementation.annotation.ReturnType; +import com.azure.core.implementation.annotation.ServiceInterface; +import com.azure.core.implementation.annotation.ServiceMethod; +import com.azure.core.implementation.annotation.UnexpectedResponseExceptionType; import com.azure.core.util.Context; import com.azure.storage.file.models.DirectorysCreateResponse; import com.azure.storage.file.models.DirectorysDeleteResponse; @@ -24,9 +26,8 @@ import com.azure.storage.file.models.DirectorysListHandlesResponse; import com.azure.storage.file.models.DirectorysSetMetadataResponse; import com.azure.storage.file.models.StorageErrorException; -import reactor.core.publisher.Mono; - import java.util.Map; +import reactor.core.publisher.Mono; /** * An instance of this class provides access to all the operations defined in @@ -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,39 +59,39 @@ public DirectorysImpl(AzureFileStorageImpl client) { * proxy service to perform REST calls. */ @Host("{url}") - @Service("Storage Files Directory") + @ServiceInterface(name = "Directorys") private interface DirectorysService { - @PUT("{shareName}/{directory}") + @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); - @GET("{shareName}/{directory}") + @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); - @DELETE("{shareName}/{directory}") + @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); - @PUT("{shareName}/{directory}") + @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); - @GET("{shareName}/{directory}") + @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); - @GET("{shareName}/{directory}") + @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); - @PUT("{shareName}/{directory}") + @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); @@ -103,6 +104,7 @@ private interface DirectorysService { * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono createWithRestResponseAsync(Context context) { final Integer timeout = null; final Map metadata = null; @@ -119,6 +121,7 @@ public Mono createWithRestResponseAsync(Context contex * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono createWithRestResponseAsync(Integer timeout, Map metadata, Context context) { final String restype = "directory"; return service.create(this.client.url(), timeout, metadata, this.client.version(), restype, context); @@ -131,6 +134,7 @@ public Mono createWithRestResponseAsync(Integer timeou * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getPropertiesWithRestResponseAsync(Context context) { final String sharesnapshot = null; final Integer timeout = null; @@ -147,6 +151,7 @@ public Mono getPropertiesWithRestResponseAsync( * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getPropertiesWithRestResponseAsync(String sharesnapshot, Integer timeout, Context context) { final String restype = "directory"; return service.getProperties(this.client.url(), sharesnapshot, timeout, this.client.version(), restype, context); @@ -159,6 +164,7 @@ public Mono getPropertiesWithRestResponseAsync( * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono deleteWithRestResponseAsync(Context context) { final Integer timeout = null; final String restype = "directory"; @@ -173,6 +179,7 @@ public Mono deleteWithRestResponseAsync(Context contex * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono deleteWithRestResponseAsync(Integer timeout, Context context) { final String restype = "directory"; return service.delete(this.client.url(), timeout, this.client.version(), restype, context); @@ -185,6 +192,7 @@ public Mono deleteWithRestResponseAsync(Integer timeou * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono setMetadataWithRestResponseAsync(Context context) { final Integer timeout = null; final Map metadata = null; @@ -202,6 +210,7 @@ public Mono setMetadataWithRestResponseAsync(Cont * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono setMetadataWithRestResponseAsync(Integer timeout, Map metadata, Context context) { final String restype = "directory"; final String comp = "metadata"; @@ -215,6 +224,7 @@ public Mono setMetadataWithRestResponseAsync(Inte * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono listFilesAndDirectoriesSegmentWithRestResponseAsync(Context context) { final String prefix = null; final String sharesnapshot = null; @@ -238,6 +248,7 @@ public Mono listFilesAndDirect * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono listFilesAndDirectoriesSegmentWithRestResponseAsync(String prefix, String sharesnapshot, String marker, Integer maxresults, Integer timeout, Context context) { final String restype = "directory"; final String comp = "list"; @@ -251,6 +262,7 @@ public Mono listFilesAndDirect * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono listHandlesWithRestResponseAsync(Context context) { final String marker = null; final Integer maxresults = null; @@ -273,6 +285,7 @@ public Mono listHandlesWithRestResponseAsync(Cont * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono listHandlesWithRestResponseAsync(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); @@ -286,6 +299,7 @@ public Mono listHandlesWithRestResponseAsync(Stri * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono forceCloseHandlesWithRestResponseAsync(String handleId, Context context) { final Integer timeout = null; final String marker = null; @@ -307,6 +321,7 @@ public Mono forceCloseHandlesWithRestRespon * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono forceCloseHandlesWithRestResponseAsync(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); 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..fde67800343f7 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 @@ -4,19 +4,21 @@ package com.azure.storage.file.implementation; -import com.azure.core.annotations.BodyParam; -import com.azure.core.annotations.DELETE; -import com.azure.core.annotations.ExpectedResponses; -import com.azure.core.annotations.GET; -import com.azure.core.annotations.HEAD; -import com.azure.core.annotations.HeaderParam; -import com.azure.core.annotations.Host; -import com.azure.core.annotations.HostParam; -import com.azure.core.annotations.PUT; -import com.azure.core.annotations.QueryParam; -import com.azure.core.annotations.Service; -import com.azure.core.annotations.UnexpectedResponseExceptionType; import com.azure.core.implementation.RestProxy; +import com.azure.core.implementation.annotation.BodyParam; +import com.azure.core.implementation.annotation.Delete; +import com.azure.core.implementation.annotation.ExpectedResponses; +import com.azure.core.implementation.annotation.Get; +import com.azure.core.implementation.annotation.Head; +import com.azure.core.implementation.annotation.HeaderParam; +import com.azure.core.implementation.annotation.Host; +import com.azure.core.implementation.annotation.HostParam; +import com.azure.core.implementation.annotation.Put; +import com.azure.core.implementation.annotation.QueryParam; +import com.azure.core.implementation.annotation.ReturnType; +import com.azure.core.implementation.annotation.ServiceInterface; +import com.azure.core.implementation.annotation.ServiceMethod; +import com.azure.core.implementation.annotation.UnexpectedResponseExceptionType; import com.azure.core.implementation.util.Base64Util; import com.azure.core.util.Context; import com.azure.storage.file.models.FileHTTPHeaders; @@ -35,11 +37,10 @@ import com.azure.storage.file.models.FilesUploadRangeResponse; import com.azure.storage.file.models.StorageErrorException; import io.netty.buffer.ByteBuf; +import java.util.Map; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -import java.util.Map; - /** * An instance of this class provides access to all the operations defined in * Files. @@ -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,63 +71,63 @@ public FilesImpl(AzureFileStorageImpl client) { * proxy service to perform REST calls. */ @Host("{url}") - @Service("Storage Files File") + @ServiceInterface(name = "Files") private interface FilesService { - @PUT("{shareName}/{directory}/{fileName}") + @Put("{shareName}/{directory}/{fileName}") @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); - @GET("{shareName}/{directory}/{fileName}") + @Get("{shareName}/{directory}/{fileName}") @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); - @HEAD("{shareName}/{directory}/{fileName}") + @Head("{shareName}/{directory}/{fileName}") @ExpectedResponses({200}) Mono getProperties(@HostParam("url") String url, @QueryParam("sharesnapshot") String sharesnapshot, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, Context context); - @DELETE("{shareName}/{directory}/{fileName}") + @Delete("{shareName}/{directory}/{fileName}") @ExpectedResponses({202}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono delete(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, Context context); - @PUT("{shareName}/{directory}/{fileName}") + @Put("{shareName}/{directory}/{fileName}") @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); - @PUT("{shareName}/{directory}/{fileName}") + @Put("{shareName}/{directory}/{fileName}") @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); - @PUT("{shareName}/{directory}/{fileName}") + @Put("{shareName}/{directory}/{fileName}") @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); - @GET("{shareName}/{directory}/{fileName}") + @Get("{shareName}/{directory}/{fileName}") @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); - @PUT("{shareName}/{directory}/{fileName}") + @Put("{shareName}/{directory}/{fileName}") @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); - @PUT("{shareName}/{directory}/{fileName}") + @Put("{shareName}/{directory}/{fileName}") @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); - @GET("{shareName}/{directory}/{fileName}") + @Get("{shareName}/{directory}/{fileName}") @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); - @PUT("{shareName}/{directory}/{fileName}") + @Put("{shareName}/{directory}/{fileName}") @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); @@ -140,6 +141,7 @@ private interface FilesService { * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono createWithRestResponseAsync(long fileContentLength, Context context) { final Integer timeout = null; final String fileTypeConstant = "file"; @@ -164,6 +166,7 @@ public Mono createWithRestResponseAsync(long fileContentLen * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono createWithRestResponseAsync(long fileContentLength, Integer timeout, Map metadata, FileHTTPHeaders fileHTTPHeaders, Context context) { final String fileTypeConstant = "file"; String fileContentType = null; @@ -201,6 +204,7 @@ public Mono createWithRestResponseAsync(long fileContentLen * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono downloadWithRestResponseAsync(Context context) { final Integer timeout = null; final String range = null; @@ -218,6 +222,7 @@ public Mono downloadWithRestResponseAsync(Context context * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono downloadWithRestResponseAsync(Integer timeout, String range, Boolean rangeGetContentMD5, Context context) { return service.download(this.client.url(), timeout, this.client.version(), range, rangeGetContentMD5, context); } @@ -229,6 +234,7 @@ public Mono downloadWithRestResponseAsync(Integer timeout * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getPropertiesWithRestResponseAsync(Context context) { final String sharesnapshot = null; final Integer timeout = null; @@ -244,6 +250,7 @@ public Mono getPropertiesWithRestResponseAsync(Conte * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getPropertiesWithRestResponseAsync(String sharesnapshot, Integer timeout, Context context) { return service.getProperties(this.client.url(), sharesnapshot, timeout, this.client.version(), context); } @@ -255,6 +262,7 @@ public Mono getPropertiesWithRestResponseAsync(Strin * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono deleteWithRestResponseAsync(Context context) { final Integer timeout = null; return service.delete(this.client.url(), timeout, this.client.version(), context); @@ -268,6 +276,7 @@ public Mono deleteWithRestResponseAsync(Context context) { * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono deleteWithRestResponseAsync(Integer timeout, Context context) { return service.delete(this.client.url(), timeout, this.client.version(), context); } @@ -279,6 +288,7 @@ public Mono deleteWithRestResponseAsync(Integer timeout, Co * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono setHTTPHeadersWithRestResponseAsync(Context context) { final Integer timeout = null; final Long fileContentLength = null; @@ -302,6 +312,7 @@ public Mono setHTTPHeadersWithRestResponseAsync(Con * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono setHTTPHeadersWithRestResponseAsync(Integer timeout, Long fileContentLength, FileHTTPHeaders fileHTTPHeaders, Context context) { final String comp = "properties"; String fileContentType = null; @@ -339,6 +350,7 @@ public Mono setHTTPHeadersWithRestResponseAsync(Int * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono setMetadataWithRestResponseAsync(Context context) { final Integer timeout = null; final Map metadata = null; @@ -355,6 +367,7 @@ public Mono setMetadataWithRestResponseAsync(Context c * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono setMetadataWithRestResponseAsync(Integer timeout, Map metadata, Context context) { final String comp = "metadata"; return service.setMetadata(this.client.url(), timeout, metadata, this.client.version(), comp, context); @@ -370,6 +383,7 @@ public Mono setMetadataWithRestResponseAsync(Integer t * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono uploadRangeWithRestResponseAsync(String range, FileRangeWriteType fileRangeWrite, long contentLength, Context context) { final Flux optionalbody = null; final Integer timeout = null; @@ -391,6 +405,7 @@ public Mono uploadRangeWithRestResponseAsync(String ra * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono uploadRangeWithRestResponseAsync(String range, FileRangeWriteType fileRangeWrite, long contentLength, Flux optionalbody, Integer timeout, byte[] contentMD5, Context context) { final String comp = "range"; String contentMD5Converted = Base64Util.encodeToString(contentMD5); @@ -404,6 +419,7 @@ public Mono uploadRangeWithRestResponseAsync(String ra * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getRangeListWithRestResponseAsync(Context context) { final String sharesnapshot = null; final Integer timeout = null; @@ -422,6 +438,7 @@ public Mono getRangeListWithRestResponseAsync(Context * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getRangeListWithRestResponseAsync(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); @@ -435,6 +452,7 @@ public Mono getRangeListWithRestResponseAsync(String * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono startCopyWithRestResponseAsync(String copySource, Context context) { final Integer timeout = null; final Map metadata = null; @@ -451,6 +469,7 @@ public Mono startCopyWithRestResponseAsync(String copySo * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono startCopyWithRestResponseAsync(String copySource, Integer timeout, Map metadata, Context context) { return service.startCopy(this.client.url(), timeout, this.client.version(), metadata, copySource, context); } @@ -463,6 +482,7 @@ public Mono startCopyWithRestResponseAsync(String copySo * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono abortCopyWithRestResponseAsync(String copyId, Context context) { final Integer timeout = null; final String copyActionAbortConstant = "abort"; @@ -479,6 +499,7 @@ public Mono abortCopyWithRestResponseAsync(String copyId * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono abortCopyWithRestResponseAsync(String copyId, Integer timeout, Context context) { final String copyActionAbortConstant = "abort"; final String comp = "copy"; @@ -492,6 +513,7 @@ public Mono abortCopyWithRestResponseAsync(String copyId * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono listHandlesWithRestResponseAsync(Context context) { final String marker = null; final Integer maxresults = null; @@ -512,6 +534,7 @@ public Mono listHandlesWithRestResponseAsync(Context c * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono listHandlesWithRestResponseAsync(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); @@ -525,6 +548,7 @@ public Mono listHandlesWithRestResponseAsync(String ma * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono forceCloseHandlesWithRestResponseAsync(String handleId, Context context) { final Integer timeout = null; final String marker = null; @@ -544,6 +568,7 @@ public Mono forceCloseHandlesWithRestResponseAsy * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono forceCloseHandlesWithRestResponseAsync(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); 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..993bbad2b93b4 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 @@ -4,18 +4,20 @@ package com.azure.storage.file.implementation; -import com.azure.core.annotations.BodyParam; -import com.azure.core.annotations.ExpectedResponses; -import com.azure.core.annotations.GET; -import com.azure.core.annotations.HeaderParam; -import com.azure.core.annotations.Host; -import com.azure.core.annotations.HostParam; -import com.azure.core.annotations.PUT; -import com.azure.core.annotations.QueryParam; -import com.azure.core.annotations.Service; -import com.azure.core.annotations.UnexpectedResponseExceptionType; import com.azure.core.implementation.CollectionFormat; import com.azure.core.implementation.RestProxy; +import com.azure.core.implementation.annotation.BodyParam; +import com.azure.core.implementation.annotation.ExpectedResponses; +import com.azure.core.implementation.annotation.Get; +import com.azure.core.implementation.annotation.HeaderParam; +import com.azure.core.implementation.annotation.Host; +import com.azure.core.implementation.annotation.HostParam; +import com.azure.core.implementation.annotation.Put; +import com.azure.core.implementation.annotation.QueryParam; +import com.azure.core.implementation.annotation.ReturnType; +import com.azure.core.implementation.annotation.ServiceInterface; +import com.azure.core.implementation.annotation.ServiceMethod; +import com.azure.core.implementation.annotation.UnexpectedResponseExceptionType; import com.azure.core.implementation.serializer.jackson.JacksonAdapter; import com.azure.core.util.Context; import com.azure.storage.file.models.ListSharesIncludeType; @@ -24,9 +26,8 @@ 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; +import reactor.core.publisher.Mono; /** * An instance of this class provides access to all the operations defined in @@ -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,19 +59,19 @@ public ServicesImpl(AzureFileStorageImpl client) { * proxy service to perform REST calls. */ @Host("{url}") - @Service("Storage Files Service") + @ServiceInterface(name = "Services") private interface ServicesService { - @PUT("") + @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); - @GET("") + @Get("") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono getProperties(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @QueryParam("restype") String restype, @QueryParam("comp") String comp, Context context); - @GET("") + @Get("") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono listSharesSegment(@HostParam("url") String url, @QueryParam("prefix") String prefix, @QueryParam("marker") String marker, @QueryParam("maxresults") Integer maxresults, @QueryParam("include") String include, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @QueryParam("comp") String comp, Context context); @@ -84,6 +85,7 @@ private interface ServicesService { * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono setPropertiesWithRestResponseAsync(StorageServiceProperties storageServiceProperties, Context context) { final Integer timeout = null; final String restype = "service"; @@ -100,6 +102,7 @@ public Mono setPropertiesWithRestResponseAsync(St * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono setPropertiesWithRestResponseAsync(StorageServiceProperties storageServiceProperties, Integer timeout, Context context) { final String restype = "service"; final String comp = "properties"; @@ -113,6 +116,7 @@ public Mono setPropertiesWithRestResponseAsync(St * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getPropertiesWithRestResponseAsync(Context context) { final Integer timeout = null; final String restype = "service"; @@ -128,6 +132,7 @@ public Mono getPropertiesWithRestResponseAsync(Co * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getPropertiesWithRestResponseAsync(Integer timeout, Context context) { final String restype = "service"; final String comp = "properties"; @@ -141,6 +146,7 @@ public Mono getPropertiesWithRestResponseAsync(In * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono listSharesSegmentWithRestResponseAsync(Context context) { final String prefix = null; final String marker = null; @@ -163,6 +169,7 @@ public Mono listSharesSegmentWithRestResponse * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono listSharesSegmentWithRestResponseAsync(String prefix, String marker, Integer maxresults, List include, Integer timeout, Context context) { final String comp = "list"; String includeConverted = JacksonAdapter.createDefaultSerializerAdapter().serializeList(include, CollectionFormat.CSV); 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..83466fe45e31e 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 @@ -4,18 +4,20 @@ package com.azure.storage.file.implementation; -import com.azure.core.annotations.BodyParam; -import com.azure.core.annotations.DELETE; -import com.azure.core.annotations.ExpectedResponses; -import com.azure.core.annotations.GET; -import com.azure.core.annotations.HeaderParam; -import com.azure.core.annotations.Host; -import com.azure.core.annotations.HostParam; -import com.azure.core.annotations.PUT; -import com.azure.core.annotations.QueryParam; -import com.azure.core.annotations.Service; -import com.azure.core.annotations.UnexpectedResponseExceptionType; import com.azure.core.implementation.RestProxy; +import com.azure.core.implementation.annotation.BodyParam; +import com.azure.core.implementation.annotation.Delete; +import com.azure.core.implementation.annotation.ExpectedResponses; +import com.azure.core.implementation.annotation.Get; +import com.azure.core.implementation.annotation.HeaderParam; +import com.azure.core.implementation.annotation.Host; +import com.azure.core.implementation.annotation.HostParam; +import com.azure.core.implementation.annotation.Put; +import com.azure.core.implementation.annotation.QueryParam; +import com.azure.core.implementation.annotation.ReturnType; +import com.azure.core.implementation.annotation.ServiceInterface; +import com.azure.core.implementation.annotation.ServiceMethod; +import com.azure.core.implementation.annotation.UnexpectedResponseExceptionType; import com.azure.core.util.Context; import com.azure.storage.file.models.DeleteSnapshotsOptionType; import com.azure.storage.file.models.SharesCreateResponse; @@ -29,10 +31,9 @@ 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 java.util.Map; +import reactor.core.publisher.Mono; /** * An instance of this class provides access to all the operations defined in @@ -55,7 +56,7 @@ public final class SharesImpl { * @param client the instance of the service client containing this operation class. */ public SharesImpl(AzureFileStorageImpl client) { - this.service = RestProxy.create(SharesService.class, client); + this.service = RestProxy.create(SharesService.class, client.httpPipeline()); this.client = client; } @@ -64,49 +65,49 @@ public SharesImpl(AzureFileStorageImpl client) { * proxy service to perform REST calls. */ @Host("{url}") - @Service("Storage Files Shares") + @ServiceInterface(name = "Shares") private interface SharesService { - @PUT("{shareName}") + @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, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-meta-") Map metadata, @HeaderParam("x-ms-share-quota") Long quota, @HeaderParam("x-ms-version") String version, @QueryParam("restype") String restype, Context context); - @GET("{shareName}") + @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); - @DELETE("{shareName}") + @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); - @PUT("{shareName}") + @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); - @PUT("{shareName}") + @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, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-share-quota") Long quota, @QueryParam("restype") String restype, @QueryParam("comp") String comp, Context context); - @PUT("{shareName}") + @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); - @GET("{shareName}") + @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); - @PUT("{shareName}") + @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); - @GET("{shareName}") + @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); @@ -119,10 +120,11 @@ private interface SharesService { * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono createWithRestResponseAsync(Context context) { final Integer timeout = null; final Map metadata = null; - final Integer quota = null; + final Long quota = null; final String restype = "share"; return service.create(this.client.url(), timeout, metadata, quota, this.client.version(), restype, context); } @@ -137,7 +139,8 @@ 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) { + @ServiceMethod(returns = ReturnType.SINGLE) + public Mono createWithRestResponseAsync(Integer timeout, Map metadata, Long quota, Context context) { final String restype = "share"; return service.create(this.client.url(), timeout, metadata, quota, this.client.version(), restype, context); } @@ -149,6 +152,7 @@ public Mono createWithRestResponseAsync(Integer timeout, M * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getPropertiesWithRestResponseAsync(Context context) { final String sharesnapshot = null; final Integer timeout = null; @@ -165,6 +169,7 @@ public Mono getPropertiesWithRestResponseAsync(Cont * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getPropertiesWithRestResponseAsync(String sharesnapshot, Integer timeout, Context context) { final String restype = "share"; return service.getProperties(this.client.url(), sharesnapshot, timeout, this.client.version(), restype, context); @@ -177,6 +182,7 @@ public Mono getPropertiesWithRestResponseAsync(Stri * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono deleteWithRestResponseAsync(Context context) { final String sharesnapshot = null; final Integer timeout = null; @@ -195,6 +201,7 @@ public Mono deleteWithRestResponseAsync(Context context) { * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono deleteWithRestResponseAsync(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); @@ -207,6 +214,7 @@ public Mono deleteWithRestResponseAsync(String sharesnapsh * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono createSnapshotWithRestResponseAsync(Context context) { final Integer timeout = null; final Map metadata = null; @@ -224,6 +232,7 @@ public Mono createSnapshotWithRestResponseAsync(Co * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono createSnapshotWithRestResponseAsync(Integer timeout, Map metadata, Context context) { final String restype = "share"; final String comp = "snapshot"; @@ -237,9 +246,10 @@ public Mono createSnapshotWithRestResponseAsync(In * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono setQuotaWithRestResponseAsync(Context context) { final Integer timeout = null; - final Integer quota = null; + final Long quota = null; final String restype = "share"; final String comp = "properties"; return service.setQuota(this.client.url(), timeout, this.client.version(), quota, restype, comp, context); @@ -254,7 +264,8 @@ public Mono setQuotaWithRestResponseAsync(Context contex * @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) { + @ServiceMethod(returns = ReturnType.SINGLE) + public Mono setQuotaWithRestResponseAsync(Integer timeout, Long 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); @@ -267,6 +278,7 @@ public Mono setQuotaWithRestResponseAsync(Integer timeou * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono setMetadataWithRestResponseAsync(Context context) { final Integer timeout = null; final Map metadata = null; @@ -284,6 +296,7 @@ public Mono setMetadataWithRestResponseAsync(Context * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono setMetadataWithRestResponseAsync(Integer timeout, Map metadata, Context context) { final String restype = "share"; final String comp = "metadata"; @@ -297,6 +310,7 @@ public Mono setMetadataWithRestResponseAsync(Integer * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getAccessPolicyWithRestResponseAsync(Context context) { final Integer timeout = null; final String restype = "share"; @@ -312,6 +326,7 @@ public Mono getAccessPolicyWithRestResponseAsync( * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getAccessPolicyWithRestResponseAsync(Integer timeout, Context context) { final String restype = "share"; final String comp = "acl"; @@ -325,6 +340,7 @@ public Mono getAccessPolicyWithRestResponseAsync( * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono setAccessPolicyWithRestResponseAsync(Context context) { final Integer timeout = null; final String restype = "share"; @@ -342,6 +358,7 @@ public Mono setAccessPolicyWithRestResponseAsync( * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono setAccessPolicyWithRestResponseAsync(List shareAcl, Integer timeout, Context context) { final String restype = "share"; final String comp = "acl"; @@ -356,6 +373,7 @@ public Mono setAccessPolicyWithRestResponseAsync( * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getStatisticsWithRestResponseAsync(Context context) { final Integer timeout = null; final String restype = "share"; @@ -371,6 +389,7 @@ public Mono getStatisticsWithRestResponseAsync(Cont * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getStatisticsWithRestResponseAsync(Integer timeout, Context context) { final String restype = "share"; final String comp = "stats"; diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/AccessPolicy.java b/storage/client/file/src/main/java/com/azure/storage/file/models/AccessPolicy.java index 94ccd39fbec5f..a5389aa6df849 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/AccessPolicy.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/AccessPolicy.java @@ -4,6 +4,7 @@ package com.azure.storage.file.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -12,6 +13,7 @@ * An Access policy. */ @JacksonXmlRootElement(localName = "AccessPolicy") +@Fluent public final class AccessPolicy { /* * The date-time the policy is active. diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/CorsRule.java b/storage/client/file/src/main/java/com/azure/storage/file/models/CorsRule.java index 998d7c00bbf93..a4419fcb6841a 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/CorsRule.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/CorsRule.java @@ -4,6 +4,7 @@ package com.azure.storage.file.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -15,6 +16,7 @@ * one domain (the origin domain) to call APIs in another domain. */ @JacksonXmlRootElement(localName = "CorsRule") +@Fluent public final class CorsRule { /* * The origin domains that are permitted to make a request against the 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/DirectoryCreateHeaders.java b/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryCreateHeaders.java index f4f14ebd7c7b4..2d9e1b99dda51 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryCreateHeaders.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryCreateHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.file.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for Create operation. */ @JacksonXmlRootElement(localName = "Directory-Create-Headers") +@Fluent public final class DirectoryCreateHeaders { /* * The ETag contains a value which represents the version of the directory, diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryDeleteHeaders.java b/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryDeleteHeaders.java index 7e98303ea6e71..a165d5a4c725f 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryDeleteHeaders.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryDeleteHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.file.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for Delete operation. */ @JacksonXmlRootElement(localName = "Directory-Delete-Headers") +@Fluent public final class DirectoryDeleteHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryForceCloseHandlesHeaders.java b/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryForceCloseHandlesHeaders.java index 08722706147e4..72a719bea1b1f 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryForceCloseHandlesHeaders.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryForceCloseHandlesHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.file.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for ForceCloseHandles operation. */ @JacksonXmlRootElement(localName = "Directory-ForceCloseHandles-Headers") +@Fluent public final class DirectoryForceCloseHandlesHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryGetPropertiesHeaders.java b/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryGetPropertiesHeaders.java index 5739160de25c7..3e42c0318f67d 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryGetPropertiesHeaders.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryGetPropertiesHeaders.java @@ -4,8 +4,9 @@ package com.azure.storage.file.models; -import com.azure.core.annotations.HeaderCollection; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; +import com.azure.core.implementation.annotation.HeaderCollection; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -15,6 +16,7 @@ * Defines headers for GetProperties operation. */ @JacksonXmlRootElement(localName = "Directory-GetProperties-Headers") +@Fluent public final class DirectoryGetPropertiesHeaders { /* * The metadata property. diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryItem.java b/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryItem.java index 4f385aee443ec..ae8703e8f0226 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryItem.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryItem.java @@ -4,6 +4,7 @@ package com.azure.storage.file.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * A listed directory item. */ @JacksonXmlRootElement(localName = "Directory") +@Fluent public final class DirectoryItem { /* * The name property. diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryListFilesAndDirectoriesSegmentHeaders.java b/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryListFilesAndDirectoriesSegmentHeaders.java index cbcd8b9d60100..c3431ac6fd12b 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryListFilesAndDirectoriesSegmentHeaders.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryListFilesAndDirectoriesSegmentHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.file.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for ListFilesAndDirectoriesSegment operation. */ @JacksonXmlRootElement(localName = "Directory-ListFilesAndDirectoriesSegment-Headers") +@Fluent public final class DirectoryListFilesAndDirectoriesSegmentHeaders { /* * Specifies the format in which the results are returned. Currently this diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryListHandlesHeaders.java b/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryListHandlesHeaders.java index c816949938439..c12065681acdb 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryListHandlesHeaders.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/DirectoryListHandlesHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.file.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for ListHandles operation. */ @JacksonXmlRootElement(localName = "Directory-ListHandles-Headers") +@Fluent public final class DirectoryListHandlesHeaders { /* * Specifies the format in which the results are returned. Currently this diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/DirectorySetMetadataHeaders.java b/storage/client/file/src/main/java/com/azure/storage/file/models/DirectorySetMetadataHeaders.java index 603bde2f285aa..01b1cfdc619bd 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/DirectorySetMetadataHeaders.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/DirectorySetMetadataHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.file.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for SetMetadata operation. */ @JacksonXmlRootElement(localName = "Directory-SetMetadata-Headers") +@Fluent public final class DirectorySetMetadataHeaders { /* * The ETag contains a value which represents the version of the directory, diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/FileAbortCopyHeaders.java b/storage/client/file/src/main/java/com/azure/storage/file/models/FileAbortCopyHeaders.java index b5a7162058d7c..d7827413292c1 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/FileAbortCopyHeaders.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/FileAbortCopyHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.file.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for AbortCopy operation. */ @JacksonXmlRootElement(localName = "File-AbortCopy-Headers") +@Fluent public final class FileAbortCopyHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/FileCreateHeaders.java b/storage/client/file/src/main/java/com/azure/storage/file/models/FileCreateHeaders.java index f294bbef75fdd..581e232cc3ceb 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/FileCreateHeaders.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/FileCreateHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.file.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for Create operation. */ @JacksonXmlRootElement(localName = "File-Create-Headers") +@Fluent public final class FileCreateHeaders { /* * The ETag contains a value which represents the version of the file, in diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/FileDeleteHeaders.java b/storage/client/file/src/main/java/com/azure/storage/file/models/FileDeleteHeaders.java index daf2668bd0521..0eca1e14caae7 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/FileDeleteHeaders.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/FileDeleteHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.file.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for Delete operation. */ @JacksonXmlRootElement(localName = "File-Delete-Headers") +@Fluent public final class FileDeleteHeaders { /* * This header uniquely identifies the request that was made and can be 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..7ac009d11d0c4 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 @@ -4,18 +4,20 @@ package com.azure.storage.file.models; -import com.azure.core.annotations.HeaderCollection; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; +import com.azure.core.implementation.annotation.HeaderCollection; +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; -import java.util.Arrays; import java.util.Map; /** * Defines headers for Download operation. */ @JacksonXmlRootElement(localName = "File-Download-Headers") +@Fluent public final class FileDownloadHeaders { /* * Returns the date and time the file was last modified. Any operation that @@ -345,7 +347,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 +364,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 +716,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); } /** @@ -728,7 +730,7 @@ public byte[] fileContentMD5() { * @return the FileDownloadHeaders object itself. */ public FileDownloadHeaders 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/FileForceCloseHandlesHeaders.java b/storage/client/file/src/main/java/com/azure/storage/file/models/FileForceCloseHandlesHeaders.java index 39f245c7d1116..34d7cf222d469 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/FileForceCloseHandlesHeaders.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/FileForceCloseHandlesHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.file.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for ForceCloseHandles operation. */ @JacksonXmlRootElement(localName = "File-ForceCloseHandles-Headers") +@Fluent public final class FileForceCloseHandlesHeaders { /* * This header uniquely identifies the request that was made and can be 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..05059ba57cc42 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 @@ -4,18 +4,20 @@ package com.azure.storage.file.models; -import com.azure.core.annotations.HeaderCollection; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; +import com.azure.core.implementation.annotation.HeaderCollection; +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; -import java.util.Arrays; import java.util.Map; /** * Defines headers for GetProperties operation. */ @JacksonXmlRootElement(localName = "File-GetProperties-Headers") +@Fluent public final class FileGetPropertiesHeaders { /* * Returns the date and time the file was last modified. The date format @@ -323,7 +325,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 +337,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/FileGetRangeListHeaders.java b/storage/client/file/src/main/java/com/azure/storage/file/models/FileGetRangeListHeaders.java index 61f16897c4fc4..94101d0b12811 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/FileGetRangeListHeaders.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/FileGetRangeListHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.file.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for GetRangeList operation. */ @JacksonXmlRootElement(localName = "File-GetRangeList-Headers") +@Fluent public final class FileGetRangeListHeaders { /* * The date/time that the file was last modified. Any operation that 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..6368cb9117d58 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,15 +4,17 @@ package com.azure.storage.file.models; +import com.azure.core.implementation.annotation.Fluent; +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; /** * Additional parameters for a set of operations, such as: Files_create, * Files_setHTTPHeaders. */ @JacksonXmlRootElement(localName = "file-HTTP-headers") +@Fluent public final class FileHTTPHeaders { /* * Sets the MIME content type of the file. The default type is @@ -146,7 +148,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 +158,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/FileItem.java b/storage/client/file/src/main/java/com/azure/storage/file/models/FileItem.java index 267445aaf42d2..2576625f162b1 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/FileItem.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/FileItem.java @@ -4,6 +4,7 @@ package com.azure.storage.file.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * A listed file item. */ @JacksonXmlRootElement(localName = "File") +@Fluent public final class FileItem { /* * The name property. diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/FileListHandlesHeaders.java b/storage/client/file/src/main/java/com/azure/storage/file/models/FileListHandlesHeaders.java index c972e5cc9db44..fe7a3fcaa5128 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/FileListHandlesHeaders.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/FileListHandlesHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.file.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for ListHandles operation. */ @JacksonXmlRootElement(localName = "File-ListHandles-Headers") +@Fluent public final class FileListHandlesHeaders { /* * Specifies the format in which the results are returned. Currently this diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/FileProperty.java b/storage/client/file/src/main/java/com/azure/storage/file/models/FileProperty.java index f045b9e209d79..38e6475dde575 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/FileProperty.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/FileProperty.java @@ -4,6 +4,7 @@ package com.azure.storage.file.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * File properties. */ @JacksonXmlRootElement(localName = "FileProperty") +@Fluent public final class FileProperty { /* * Content length of the file. This value may not be up-to-date since an diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/FileSetHTTPHeadersHeaders.java b/storage/client/file/src/main/java/com/azure/storage/file/models/FileSetHTTPHeadersHeaders.java index 178e2f0cd66ba..6d50bff6a3ca5 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/FileSetHTTPHeadersHeaders.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/FileSetHTTPHeadersHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.file.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for SetHTTPHeaders operation. */ @JacksonXmlRootElement(localName = "File-SetHTTPHeaders-Headers") +@Fluent public final class FileSetHTTPHeadersHeaders { /* * The ETag contains a value which represents the version of the file, in diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/FileSetMetadataHeaders.java b/storage/client/file/src/main/java/com/azure/storage/file/models/FileSetMetadataHeaders.java index 98fa0ac8d2dc7..4d199c3601c0f 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/FileSetMetadataHeaders.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/FileSetMetadataHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.file.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for SetMetadata operation. */ @JacksonXmlRootElement(localName = "File-SetMetadata-Headers") +@Fluent public final class FileSetMetadataHeaders { /* * The ETag contains a value which represents the version of the file, in diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/FileStartCopyHeaders.java b/storage/client/file/src/main/java/com/azure/storage/file/models/FileStartCopyHeaders.java index 939ed8e062949..1deb930d421a7 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/FileStartCopyHeaders.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/FileStartCopyHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.file.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for StartCopy operation. */ @JacksonXmlRootElement(localName = "File-StartCopy-Headers") +@Fluent public final class FileStartCopyHeaders { /* * If the copy is completed, contains the ETag of the destination file. If 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..5ff931c341c53 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,15 +5,17 @@ package com.azure.storage.file.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; +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; -import java.util.Arrays; /** * Defines headers for UploadRange operation. */ @JacksonXmlRootElement(localName = "File-UploadRange-Headers") +@Fluent public final class FileUploadRangeHeaders { /* * The ETag contains a value which represents the version of the file, in @@ -138,7 +140,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 +153,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/FilesAndDirectoriesListSegment.java b/storage/client/file/src/main/java/com/azure/storage/file/models/FilesAndDirectoriesListSegment.java index b5b88d30e4b70..8888fe5a155c3 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/FilesAndDirectoriesListSegment.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/FilesAndDirectoriesListSegment.java @@ -4,6 +4,7 @@ package com.azure.storage.file.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.util.ArrayList; @@ -13,6 +14,7 @@ * Abstract for entries that can be listed from Directory. */ @JacksonXmlRootElement(localName = "Entries") +@Fluent public final class FilesAndDirectoriesListSegment { /* * The directoryItems property. diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/HandleItem.java b/storage/client/file/src/main/java/com/azure/storage/file/models/HandleItem.java index a6f6d360a65e9..485ede45110e6 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/HandleItem.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/HandleItem.java @@ -5,6 +5,7 @@ package com.azure.storage.file.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * A listed Azure Storage handle item. */ @JacksonXmlRootElement(localName = "Handle") +@Fluent public final class HandleItem { /* * XSMB service handle ID 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..a1b837aec2516 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 @@ -4,6 +4,7 @@ package com.azure.storage.file.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -12,6 +13,7 @@ * An enumeration of directories and files. */ @JacksonXmlRootElement(localName = "EnumerationResults") +@Fluent public final class ListFilesAndDirectoriesSegmentResponse { /* * The serviceEndpoint property. diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/ListHandlesResponse.java b/storage/client/file/src/main/java/com/azure/storage/file/models/ListHandlesResponse.java index 0592fa5d4e37e..b344237919240 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/ListHandlesResponse.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/ListHandlesResponse.java @@ -4,6 +4,7 @@ package com.azure.storage.file.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; @@ -15,6 +16,7 @@ * An enumeration of handles. */ @JacksonXmlRootElement(localName = "EnumerationResults") +@Fluent public final class ListHandlesResponse { private static final class EntriesWrapper { @JacksonXmlProperty(localName = "Handle") diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/ListSharesResponse.java b/storage/client/file/src/main/java/com/azure/storage/file/models/ListSharesResponse.java index 97a7c340f5b69..02057898a9a34 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/ListSharesResponse.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/ListSharesResponse.java @@ -4,6 +4,7 @@ package com.azure.storage.file.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; @@ -15,6 +16,7 @@ * An enumeration of shares. */ @JacksonXmlRootElement(localName = "EnumerationResults") +@Fluent public final class ListSharesResponse { /* * The serviceEndpoint property. diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/Metrics.java b/storage/client/file/src/main/java/com/azure/storage/file/models/Metrics.java index a6272111de5ef..c0dd3fbffc8d2 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/Metrics.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/Metrics.java @@ -4,6 +4,7 @@ package com.azure.storage.file.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * Storage Analytics metrics for file service. */ @JacksonXmlRootElement(localName = "Metrics") +@Fluent public final class Metrics { /* * The version of Storage Analytics to configure. diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/Range.java b/storage/client/file/src/main/java/com/azure/storage/file/models/Range.java index d097cb3af18be..78bdfb86afb8e 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/Range.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/Range.java @@ -4,6 +4,7 @@ package com.azure.storage.file.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * An Azure Storage file range. */ @JacksonXmlRootElement(localName = "Range") +@Fluent public final class Range { /* * Start of the range. diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/RetentionPolicy.java b/storage/client/file/src/main/java/com/azure/storage/file/models/RetentionPolicy.java index 9e8cb19acd17b..7df72050787a3 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/RetentionPolicy.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/RetentionPolicy.java @@ -4,6 +4,7 @@ package com.azure.storage.file.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * The retention policy. */ @JacksonXmlRootElement(localName = "RetentionPolicy") +@Fluent public final class RetentionPolicy { /* * Indicates whether a retention policy is enabled for the File service. If diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/ServiceGetPropertiesHeaders.java b/storage/client/file/src/main/java/com/azure/storage/file/models/ServiceGetPropertiesHeaders.java index 409494366dcf8..df71dd916dfdf 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/ServiceGetPropertiesHeaders.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/ServiceGetPropertiesHeaders.java @@ -4,6 +4,7 @@ package com.azure.storage.file.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * Defines headers for GetProperties operation. */ @JacksonXmlRootElement(localName = "Service-GetProperties-Headers") +@Fluent public final class ServiceGetPropertiesHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/ServiceListSharesSegmentHeaders.java b/storage/client/file/src/main/java/com/azure/storage/file/models/ServiceListSharesSegmentHeaders.java index a735f1b81589d..f01750e386dc7 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/ServiceListSharesSegmentHeaders.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/ServiceListSharesSegmentHeaders.java @@ -4,6 +4,7 @@ package com.azure.storage.file.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * Defines headers for ListSharesSegment operation. */ @JacksonXmlRootElement(localName = "Service-ListSharesSegment-Headers") +@Fluent public final class ServiceListSharesSegmentHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/ServiceSetPropertiesHeaders.java b/storage/client/file/src/main/java/com/azure/storage/file/models/ServiceSetPropertiesHeaders.java index 43ce484399730..427b395e5fdba 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/ServiceSetPropertiesHeaders.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/ServiceSetPropertiesHeaders.java @@ -4,6 +4,7 @@ package com.azure.storage.file.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * Defines headers for SetProperties operation. */ @JacksonXmlRootElement(localName = "Service-SetProperties-Headers") +@Fluent public final class ServiceSetPropertiesHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/ShareCreateHeaders.java b/storage/client/file/src/main/java/com/azure/storage/file/models/ShareCreateHeaders.java index 32ec5a693c9fc..1f0e4f443f0df 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/ShareCreateHeaders.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/ShareCreateHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.file.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for Create operation. */ @JacksonXmlRootElement(localName = "Share-Create-Headers") +@Fluent public final class ShareCreateHeaders { /* * The ETag contains a value which represents the version of the share, in diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/ShareCreateSnapshotHeaders.java b/storage/client/file/src/main/java/com/azure/storage/file/models/ShareCreateSnapshotHeaders.java index 5163b958e1a2d..23317403ce6e6 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/ShareCreateSnapshotHeaders.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/ShareCreateSnapshotHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.file.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for CreateSnapshot operation. */ @JacksonXmlRootElement(localName = "Share-CreateSnapshot-Headers") +@Fluent public final class ShareCreateSnapshotHeaders { /* * This header is a DateTime value that uniquely identifies the share diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/ShareDeleteHeaders.java b/storage/client/file/src/main/java/com/azure/storage/file/models/ShareDeleteHeaders.java index ce8c796eba7c6..5489676b7fd02 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/ShareDeleteHeaders.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/ShareDeleteHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.file.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for Delete operation. */ @JacksonXmlRootElement(localName = "Share-Delete-Headers") +@Fluent public final class ShareDeleteHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/ShareGetAccessPolicyHeaders.java b/storage/client/file/src/main/java/com/azure/storage/file/models/ShareGetAccessPolicyHeaders.java index 9988562a78509..cb6b86a1acb10 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/ShareGetAccessPolicyHeaders.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/ShareGetAccessPolicyHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.file.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for GetAccessPolicy operation. */ @JacksonXmlRootElement(localName = "Share-GetAccessPolicy-Headers") +@Fluent public final class ShareGetAccessPolicyHeaders { /* * The ETag contains a value that you can use to perform operations diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/ShareGetPropertiesHeaders.java b/storage/client/file/src/main/java/com/azure/storage/file/models/ShareGetPropertiesHeaders.java index c9534dc5060b2..56b7093c71b67 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/ShareGetPropertiesHeaders.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/ShareGetPropertiesHeaders.java @@ -4,8 +4,9 @@ package com.azure.storage.file.models; -import com.azure.core.annotations.HeaderCollection; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; +import com.azure.core.implementation.annotation.HeaderCollection; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -15,6 +16,7 @@ * Defines headers for GetProperties operation. */ @JacksonXmlRootElement(localName = "Share-GetProperties-Headers") +@Fluent public final class ShareGetPropertiesHeaders { /* * The metadata property. @@ -62,7 +64,7 @@ public final class ShareGetPropertiesHeaders { * Returns the current share quota in GB. */ @JsonProperty(value = "x-ms-share-quota") - private Integer quota; + private Long quota; /* * The errorCode property. @@ -223,7 +225,7 @@ public ShareGetPropertiesHeaders dateProperty(OffsetDateTime dateProperty) { * * @return the quota value. */ - public Integer quota() { + public Long quota() { return this.quota; } @@ -233,7 +235,7 @@ public Integer quota() { * @param quota the quota value to set. * @return the ShareGetPropertiesHeaders object itself. */ - public ShareGetPropertiesHeaders quota(Integer quota) { + public ShareGetPropertiesHeaders quota(Long quota) { this.quota = quota; return this; } diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/ShareGetStatisticsHeaders.java b/storage/client/file/src/main/java/com/azure/storage/file/models/ShareGetStatisticsHeaders.java index 575cafb0351a9..453dcd186401c 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/ShareGetStatisticsHeaders.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/ShareGetStatisticsHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.file.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for GetStatistics operation. */ @JacksonXmlRootElement(localName = "Share-GetStatistics-Headers") +@Fluent public final class ShareGetStatisticsHeaders { /* * The ETag contains a value that you can use to perform operations diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/ShareItem.java b/storage/client/file/src/main/java/com/azure/storage/file/models/ShareItem.java index 23a64ac334548..cdec4f96b31b7 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/ShareItem.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/ShareItem.java @@ -4,6 +4,7 @@ package com.azure.storage.file.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.util.Map; @@ -12,6 +13,7 @@ * A listed Azure Storage share item. */ @JacksonXmlRootElement(localName = "Share") +@Fluent public final class ShareItem { /* * The name property. diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/ShareProperties.java b/storage/client/file/src/main/java/com/azure/storage/file/models/ShareProperties.java index 66e92994f800e..26963cecced68 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/ShareProperties.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/ShareProperties.java @@ -5,6 +5,7 @@ package com.azure.storage.file.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Properties of a share. */ @JacksonXmlRootElement(localName = "ShareProperties") +@Fluent public final class ShareProperties { /* * The lastModified property. @@ -30,7 +32,7 @@ public final class ShareProperties { * The quota property. */ @JsonProperty(value = "Quota", required = true) - private int quota; + private long quota; /** * Get the lastModified property: The lastModified property. @@ -84,7 +86,7 @@ public ShareProperties etag(String etag) { * * @return the quota value. */ - public int quota() { + public long quota() { return this.quota; } @@ -94,7 +96,7 @@ public int quota() { * @param quota the quota value to set. * @return the ShareProperties object itself. */ - public ShareProperties quota(int quota) { + public ShareProperties quota(long quota) { this.quota = quota; return this; } diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/ShareSetAccessPolicyHeaders.java b/storage/client/file/src/main/java/com/azure/storage/file/models/ShareSetAccessPolicyHeaders.java index 4a688b1d61e4d..92e0c470cd045 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/ShareSetAccessPolicyHeaders.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/ShareSetAccessPolicyHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.file.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for SetAccessPolicy operation. */ @JacksonXmlRootElement(localName = "Share-SetAccessPolicy-Headers") +@Fluent public final class ShareSetAccessPolicyHeaders { /* * The ETag contains a value that you can use to perform operations diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/ShareSetMetadataHeaders.java b/storage/client/file/src/main/java/com/azure/storage/file/models/ShareSetMetadataHeaders.java index f92662e355a14..2d11c4a6b9d79 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/ShareSetMetadataHeaders.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/ShareSetMetadataHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.file.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for SetMetadata operation. */ @JacksonXmlRootElement(localName = "Share-SetMetadata-Headers") +@Fluent public final class ShareSetMetadataHeaders { /* * The ETag contains a value that you can use to perform operations diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/ShareSetQuotaHeaders.java b/storage/client/file/src/main/java/com/azure/storage/file/models/ShareSetQuotaHeaders.java index 819b1046c923b..75ea625a4a27c 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/ShareSetQuotaHeaders.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/ShareSetQuotaHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.file.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for SetQuota operation. */ @JacksonXmlRootElement(localName = "Share-SetQuota-Headers") +@Fluent public final class ShareSetQuotaHeaders { /* * The ETag contains a value that you can use to perform operations diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/ShareStats.java b/storage/client/file/src/main/java/com/azure/storage/file/models/ShareStats.java index 6738332eb4709..8d3c2c6e69df5 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/ShareStats.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/ShareStats.java @@ -4,6 +4,7 @@ package com.azure.storage.file.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * Stats for the share. */ @JacksonXmlRootElement(localName = "ShareStats") +@Fluent public final class ShareStats { /* * The approximate size of the data stored in bytes, rounded up to the diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/SignedIdentifier.java b/storage/client/file/src/main/java/com/azure/storage/file/models/SignedIdentifier.java index 566ab7070c713..242c647f5bae8 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/SignedIdentifier.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/SignedIdentifier.java @@ -4,6 +4,7 @@ package com.azure.storage.file.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * Signed identifier. */ @JacksonXmlRootElement(localName = "SignedIdentifier") +@Fluent public final class SignedIdentifier { /* * A unique id. diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/StorageError.java b/storage/client/file/src/main/java/com/azure/storage/file/models/StorageError.java index 801db72d87c0a..b7274f2afb950 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/StorageError.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/StorageError.java @@ -4,6 +4,7 @@ package com.azure.storage.file.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * The StorageError model. */ @JacksonXmlRootElement(localName = "StorageError") +@Fluent public final class StorageError { /* * The message property. diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/StorageServiceProperties.java b/storage/client/file/src/main/java/com/azure/storage/file/models/StorageServiceProperties.java index 360b85491edf1..e3892f5f2c4ba 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/StorageServiceProperties.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/StorageServiceProperties.java @@ -4,6 +4,7 @@ package com.azure.storage.file.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; @@ -15,6 +16,7 @@ * Storage service properties. */ @JacksonXmlRootElement(localName = "StorageServiceProperties") +@Fluent public final class StorageServiceProperties { /* * A summary of request statistics grouped by API in hourly aggregates for diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/AzureQueueStorageBuilder.java b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/AzureQueueStorageBuilder.java index 4f678dfe10832..b8fc2de79856e 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/AzureQueueStorageBuilder.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/AzureQueueStorageBuilder.java @@ -6,10 +6,12 @@ import com.azure.core.http.HttpPipeline; import com.azure.core.implementation.RestProxy; +import com.azure.core.implementation.annotation.ServiceClientBuilder; /** - * A appendBlobClientBuilder for creating a new instance of the AzureQueueStorage type. + * A builder for creating a new instance of the AzureQueueStorage type. */ +@ServiceClientBuilder(serviceClients = AzureQueueStorageImpl.class) public final class AzureQueueStorageBuilder { /* * The URL of the service account, queue or message that is the targe of the desired operation. diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/AzureQueueStorageImpl.java b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/AzureQueueStorageImpl.java index 1573b9c7e05bd..4288bcc04b487 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/AzureQueueStorageImpl.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/AzureQueueStorageImpl.java @@ -4,14 +4,13 @@ package com.azure.storage.queue.implementation; -import com.azure.core.ServiceClient; import com.azure.core.http.HttpPipeline; import com.azure.core.implementation.RestProxy; /** * Initializes a new instance of the AzureQueueStorage type. */ -public final class AzureQueueStorageImpl extends ServiceClient { +public final class AzureQueueStorageImpl { /** * The URL of the service account, queue or message that is the targe of the desired operation. */ @@ -62,6 +61,20 @@ AzureQueueStorageImpl version(String version) { return this; } + /** + * The HTTP pipeline to send requests through. + */ + private HttpPipeline httpPipeline; + + /** + * Gets The HTTP pipeline to send requests through. + * + * @return the httpPipeline value. + */ + public HttpPipeline httpPipeline() { + return this.httpPipeline; + } + /** * The ServicesImpl object to access its operations. */ @@ -131,7 +144,7 @@ public AzureQueueStorageImpl() { * @param httpPipeline The HTTP pipeline to send requests through. */ public AzureQueueStorageImpl(HttpPipeline httpPipeline) { - super(httpPipeline); + this.httpPipeline = httpPipeline; this.services = new ServicesImpl(this); this.queues = new QueuesImpl(this); this.messages = new MessagesImpl(this); diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessageIdsImpl.java b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessageIdsImpl.java index 8a705fe7e4af7..611e58170b3c8 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessageIdsImpl.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessageIdsImpl.java @@ -4,17 +4,19 @@ package com.azure.storage.queue.implementation; -import com.azure.core.annotations.BodyParam; -import com.azure.core.annotations.DELETE; -import com.azure.core.annotations.ExpectedResponses; -import com.azure.core.annotations.HeaderParam; -import com.azure.core.annotations.Host; -import com.azure.core.annotations.HostParam; -import com.azure.core.annotations.PUT; -import com.azure.core.annotations.QueryParam; -import com.azure.core.annotations.Service; -import com.azure.core.annotations.UnexpectedResponseExceptionType; import com.azure.core.implementation.RestProxy; +import com.azure.core.implementation.annotation.BodyParam; +import com.azure.core.implementation.annotation.Delete; +import com.azure.core.implementation.annotation.ExpectedResponses; +import com.azure.core.implementation.annotation.HeaderParam; +import com.azure.core.implementation.annotation.Host; +import com.azure.core.implementation.annotation.HostParam; +import com.azure.core.implementation.annotation.Put; +import com.azure.core.implementation.annotation.QueryParam; +import com.azure.core.implementation.annotation.ReturnType; +import com.azure.core.implementation.annotation.ServiceInterface; +import com.azure.core.implementation.annotation.ServiceMethod; +import com.azure.core.implementation.annotation.UnexpectedResponseExceptionType; import com.azure.core.util.Context; import com.azure.storage.queue.models.MessageIdsDeleteResponse; import com.azure.storage.queue.models.MessageIdsUpdateResponse; @@ -43,7 +45,7 @@ public final class MessageIdsImpl { * @param client the instance of the service client containing this operation class. */ public MessageIdsImpl(AzureQueueStorageImpl client) { - this.service = RestProxy.create(MessageIdsService.class, client); + this.service = RestProxy.create(MessageIdsService.class, client.httpPipeline()); this.client = client; } @@ -52,14 +54,14 @@ public MessageIdsImpl(AzureQueueStorageImpl client) { * proxy service to perform REST calls. */ @Host("{url}") - @Service("Storage Queues MessageId") + @ServiceInterface(name = "MessageIds") private interface MessageIdsService { - @PUT("{queueName}/messages/{messageid}") + @Put("{queueName}/messages/{messageid}") @ExpectedResponses({204}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono update(@HostParam("url") String url, @BodyParam("application/xml; charset=utf-8") QueueMessage queueMessage, @QueryParam("popreceipt") String popReceipt, @QueryParam("visibilitytimeout") int visibilitytimeout, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context); - @DELETE("{queueName}/messages/{messageid}") + @Delete("{queueName}/messages/{messageid}") @ExpectedResponses({204}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono delete(@HostParam("url") String url, @QueryParam("popreceipt") String popReceipt, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context); @@ -75,6 +77,7 @@ private interface MessageIdsService { * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono updateWithRestResponseAsync(QueueMessage queueMessage, String popReceipt, int visibilitytimeout, Context context) { final Integer timeout = null; final String requestId = null; @@ -93,6 +96,7 @@ public Mono updateWithRestResponseAsync(QueueMessage q * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono updateWithRestResponseAsync(QueueMessage queueMessage, String popReceipt, int visibilitytimeout, Integer timeout, String requestId, Context context) { return service.update(this.client.url(), queueMessage, popReceipt, visibilitytimeout, timeout, this.client.version(), requestId, context); } @@ -105,6 +109,7 @@ public Mono updateWithRestResponseAsync(QueueMessage q * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono deleteWithRestResponseAsync(String popReceipt, Context context) { final Integer timeout = null; final String requestId = null; @@ -121,6 +126,7 @@ public Mono deleteWithRestResponseAsync(String popRece * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono deleteWithRestResponseAsync(String popReceipt, Integer timeout, String requestId, Context context) { return service.delete(this.client.url(), popReceipt, timeout, this.client.version(), requestId, context); } diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessagesImpl.java b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessagesImpl.java index ee59aae16b63f..32809752caebc 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessagesImpl.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessagesImpl.java @@ -4,18 +4,20 @@ package com.azure.storage.queue.implementation; -import com.azure.core.annotations.BodyParam; -import com.azure.core.annotations.DELETE; -import com.azure.core.annotations.ExpectedResponses; -import com.azure.core.annotations.GET; -import com.azure.core.annotations.HeaderParam; -import com.azure.core.annotations.Host; -import com.azure.core.annotations.HostParam; -import com.azure.core.annotations.POST; -import com.azure.core.annotations.QueryParam; -import com.azure.core.annotations.Service; -import com.azure.core.annotations.UnexpectedResponseExceptionType; import com.azure.core.implementation.RestProxy; +import com.azure.core.implementation.annotation.BodyParam; +import com.azure.core.implementation.annotation.Delete; +import com.azure.core.implementation.annotation.ExpectedResponses; +import com.azure.core.implementation.annotation.Get; +import com.azure.core.implementation.annotation.HeaderParam; +import com.azure.core.implementation.annotation.Host; +import com.azure.core.implementation.annotation.HostParam; +import com.azure.core.implementation.annotation.Post; +import com.azure.core.implementation.annotation.QueryParam; +import com.azure.core.implementation.annotation.ReturnType; +import com.azure.core.implementation.annotation.ServiceInterface; +import com.azure.core.implementation.annotation.ServiceMethod; +import com.azure.core.implementation.annotation.UnexpectedResponseExceptionType; import com.azure.core.util.Context; import com.azure.storage.queue.models.MessagesClearResponse; import com.azure.storage.queue.models.MessagesDequeueResponse; @@ -46,7 +48,7 @@ public final class MessagesImpl { * @param client the instance of the service client containing this operation class. */ public MessagesImpl(AzureQueueStorageImpl client) { - this.service = RestProxy.create(MessagesService.class, client); + this.service = RestProxy.create(MessagesService.class, client.httpPipeline()); this.client = client; } @@ -55,24 +57,24 @@ public MessagesImpl(AzureQueueStorageImpl client) { * proxy service to perform REST calls. */ @Host("{url}") - @Service("Storage Queues Messages") + @ServiceInterface(name = "Messages") private interface MessagesService { - @GET("{queueName}/messages") + @Get("{queueName}/messages") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono dequeue(@HostParam("url") String url, @QueryParam("numofmessages") Integer numberOfMessages, @QueryParam("visibilitytimeout") Integer visibilitytimeout, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context); - @DELETE("{queueName}/messages") + @Delete("{queueName}/messages") @ExpectedResponses({204}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono clear(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context); - @POST("{queueName}/messages") + @Post("{queueName}/messages") @ExpectedResponses({201}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono enqueue(@HostParam("url") String url, @BodyParam("application/xml; charset=utf-8") QueueMessage queueMessage, @QueryParam("visibilitytimeout") Integer visibilitytimeout, @QueryParam("messagettl") Integer messageTimeToLive, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context); - @GET("{queueName}/messages") + @Get("{queueName}/messages") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono peek(@HostParam("url") String url, @QueryParam("numofmessages") Integer numberOfMessages, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("peekonly") String peekonly, Context context); @@ -85,6 +87,7 @@ private interface MessagesService { * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono dequeueWithRestResponseAsync(Context context) { final Integer numberOfMessages = null; final Integer visibilitytimeout = null; @@ -104,6 +107,7 @@ public Mono dequeueWithRestResponseAsync(Context contex * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono dequeueWithRestResponseAsync(Integer numberOfMessages, Integer visibilitytimeout, Integer timeout, String requestId, Context context) { return service.dequeue(this.client.url(), numberOfMessages, visibilitytimeout, timeout, this.client.version(), requestId, context); } @@ -115,6 +119,7 @@ public Mono dequeueWithRestResponseAsync(Integer number * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono clearWithRestResponseAsync(Context context) { final Integer timeout = null; final String requestId = null; @@ -130,6 +135,7 @@ public Mono clearWithRestResponseAsync(Context context) { * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono clearWithRestResponseAsync(Integer timeout, String requestId, Context context) { return service.clear(this.client.url(), timeout, this.client.version(), requestId, context); } @@ -142,6 +148,7 @@ public Mono clearWithRestResponseAsync(Integer timeout, S * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono enqueueWithRestResponseAsync(QueueMessage queueMessage, Context context) { final Integer visibilitytimeout = null; final Integer messageTimeToLive = null; @@ -162,6 +169,7 @@ public Mono enqueueWithRestResponseAsync(QueueMessage q * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono enqueueWithRestResponseAsync(QueueMessage queueMessage, Integer visibilitytimeout, Integer messageTimeToLive, Integer timeout, String requestId, Context context) { return service.enqueue(this.client.url(), queueMessage, visibilitytimeout, messageTimeToLive, timeout, this.client.version(), requestId, context); } @@ -173,6 +181,7 @@ public Mono enqueueWithRestResponseAsync(QueueMessage q * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono peekWithRestResponseAsync(Context context) { final Integer numberOfMessages = null; final Integer timeout = null; @@ -191,6 +200,7 @@ public Mono peekWithRestResponseAsync(Context context) { * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono peekWithRestResponseAsync(Integer numberOfMessages, Integer timeout, String requestId, Context context) { final String peekonly = "true"; return service.peek(this.client.url(), numberOfMessages, timeout, this.client.version(), requestId, peekonly, context); diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/QueuesImpl.java b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/QueuesImpl.java index 2eb2d4d1ec2e2..9665d355022b3 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/QueuesImpl.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/QueuesImpl.java @@ -4,18 +4,20 @@ package com.azure.storage.queue.implementation; -import com.azure.core.annotations.BodyParam; -import com.azure.core.annotations.DELETE; -import com.azure.core.annotations.ExpectedResponses; -import com.azure.core.annotations.GET; -import com.azure.core.annotations.HeaderParam; -import com.azure.core.annotations.Host; -import com.azure.core.annotations.HostParam; -import com.azure.core.annotations.PUT; -import com.azure.core.annotations.QueryParam; -import com.azure.core.annotations.Service; -import com.azure.core.annotations.UnexpectedResponseExceptionType; import com.azure.core.implementation.RestProxy; +import com.azure.core.implementation.annotation.BodyParam; +import com.azure.core.implementation.annotation.Delete; +import com.azure.core.implementation.annotation.ExpectedResponses; +import com.azure.core.implementation.annotation.Get; +import com.azure.core.implementation.annotation.HeaderParam; +import com.azure.core.implementation.annotation.Host; +import com.azure.core.implementation.annotation.HostParam; +import com.azure.core.implementation.annotation.Put; +import com.azure.core.implementation.annotation.QueryParam; +import com.azure.core.implementation.annotation.ReturnType; +import com.azure.core.implementation.annotation.ServiceInterface; +import com.azure.core.implementation.annotation.ServiceMethod; +import com.azure.core.implementation.annotation.UnexpectedResponseExceptionType; import com.azure.core.util.Context; import com.azure.storage.queue.models.QueuesCreateResponse; import com.azure.storage.queue.models.QueuesDeleteResponse; @@ -25,10 +27,9 @@ import com.azure.storage.queue.models.QueuesSetMetadataResponse; import com.azure.storage.queue.models.SignedIdentifier; import com.azure.storage.queue.models.StorageErrorException; -import reactor.core.publisher.Mono; - import java.util.List; import java.util.Map; +import reactor.core.publisher.Mono; /** * An instance of this class provides access to all the operations defined in @@ -51,7 +52,7 @@ public final class QueuesImpl { * @param client the instance of the service client containing this operation class. */ public QueuesImpl(AzureQueueStorageImpl client) { - this.service = RestProxy.create(QueuesService.class, client); + this.service = RestProxy.create(QueuesService.class, client.httpPipeline()); this.client = client; } @@ -60,34 +61,34 @@ public QueuesImpl(AzureQueueStorageImpl client) { * proxy service to perform REST calls. */ @Host("{url}") - @Service("Storage Queues Queue") + @ServiceInterface(name = "Queues") private interface QueuesService { - @PUT("{queueName}") + @Put("{queueName}") @ExpectedResponses({201, 204}) @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, @HeaderParam("x-ms-client-request-id") String requestId, Context context); - @DELETE("{queueName}") + @Delete("{queueName}") @ExpectedResponses({204}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono delete(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context); - @GET("{queueName}") + @Get("{queueName}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono getProperties(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, Context context); - @PUT("{queueName}") + @Put("{queueName}") @ExpectedResponses({204}) @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, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, Context context); - @GET("{queueName}") + @Get("{queueName}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono getAccessPolicy(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, Context context); - @PUT("{queueName}") + @Put("{queueName}") @ExpectedResponses({204}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono setAccessPolicy(@HostParam("url") String url, @BodyParam("application/xml; charset=utf-8") SignedIdentifiersWrapper queueAcl, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, Context context); @@ -100,6 +101,7 @@ private interface QueuesService { * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono createWithRestResponseAsync(Context context) { final Integer timeout = null; final Map metadata = null; @@ -117,6 +119,7 @@ public Mono createWithRestResponseAsync(Context context) { * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono createWithRestResponseAsync(Integer timeout, Map metadata, String requestId, Context context) { return service.create(this.client.url(), timeout, metadata, this.client.version(), requestId, context); } @@ -128,6 +131,7 @@ public Mono createWithRestResponseAsync(Integer timeout, M * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono deleteWithRestResponseAsync(Context context) { final Integer timeout = null; final String requestId = null; @@ -143,6 +147,7 @@ public Mono deleteWithRestResponseAsync(Context context) { * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono deleteWithRestResponseAsync(Integer timeout, String requestId, Context context) { return service.delete(this.client.url(), timeout, this.client.version(), requestId, context); } @@ -154,6 +159,7 @@ public Mono deleteWithRestResponseAsync(Integer timeout, S * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getPropertiesWithRestResponseAsync(Context context) { final Integer timeout = null; final String requestId = null; @@ -170,6 +176,7 @@ public Mono getPropertiesWithRestResponseAsync(Cont * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getPropertiesWithRestResponseAsync(Integer timeout, String requestId, Context context) { final String comp = "metadata"; return service.getProperties(this.client.url(), timeout, this.client.version(), requestId, comp, context); @@ -182,6 +189,7 @@ public Mono getPropertiesWithRestResponseAsync(Inte * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono setMetadataWithRestResponseAsync(Context context) { final Integer timeout = null; final Map metadata = null; @@ -200,6 +208,7 @@ public Mono setMetadataWithRestResponseAsync(Context * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono setMetadataWithRestResponseAsync(Integer timeout, Map metadata, String requestId, Context context) { final String comp = "metadata"; return service.setMetadata(this.client.url(), timeout, metadata, this.client.version(), requestId, comp, context); @@ -212,6 +221,7 @@ public Mono setMetadataWithRestResponseAsync(Integer * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getAccessPolicyWithRestResponseAsync(Context context) { final Integer timeout = null; final String requestId = null; @@ -228,6 +238,7 @@ public Mono getAccessPolicyWithRestResponseAsync( * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getAccessPolicyWithRestResponseAsync(Integer timeout, String requestId, Context context) { final String comp = "acl"; return service.getAccessPolicy(this.client.url(), timeout, this.client.version(), requestId, comp, context); @@ -240,6 +251,7 @@ public Mono getAccessPolicyWithRestResponseAsync( * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono setAccessPolicyWithRestResponseAsync(Context context) { final Integer timeout = null; final String requestId = null; @@ -258,6 +270,7 @@ public Mono setAccessPolicyWithRestResponseAsync( * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono setAccessPolicyWithRestResponseAsync(List queueAcl, Integer timeout, String requestId, Context context) { final String comp = "acl"; SignedIdentifiersWrapper queueAclConverted = new SignedIdentifiersWrapper(queueAcl); diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/ServicesImpl.java b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/ServicesImpl.java index dc353d45f5243..32fc830c6b168 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/ServicesImpl.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/ServicesImpl.java @@ -4,18 +4,20 @@ package com.azure.storage.queue.implementation; -import com.azure.core.annotations.BodyParam; -import com.azure.core.annotations.ExpectedResponses; -import com.azure.core.annotations.GET; -import com.azure.core.annotations.HeaderParam; -import com.azure.core.annotations.Host; -import com.azure.core.annotations.HostParam; -import com.azure.core.annotations.PUT; -import com.azure.core.annotations.QueryParam; -import com.azure.core.annotations.Service; -import com.azure.core.annotations.UnexpectedResponseExceptionType; import com.azure.core.implementation.CollectionFormat; import com.azure.core.implementation.RestProxy; +import com.azure.core.implementation.annotation.BodyParam; +import com.azure.core.implementation.annotation.ExpectedResponses; +import com.azure.core.implementation.annotation.Get; +import com.azure.core.implementation.annotation.HeaderParam; +import com.azure.core.implementation.annotation.Host; +import com.azure.core.implementation.annotation.HostParam; +import com.azure.core.implementation.annotation.Put; +import com.azure.core.implementation.annotation.QueryParam; +import com.azure.core.implementation.annotation.ReturnType; +import com.azure.core.implementation.annotation.ServiceInterface; +import com.azure.core.implementation.annotation.ServiceMethod; +import com.azure.core.implementation.annotation.UnexpectedResponseExceptionType; import com.azure.core.implementation.serializer.jackson.JacksonAdapter; import com.azure.core.util.Context; import com.azure.storage.queue.models.ListQueuesIncludeType; @@ -25,9 +27,8 @@ import com.azure.storage.queue.models.ServicesSetPropertiesResponse; import com.azure.storage.queue.models.StorageErrorException; import com.azure.storage.queue.models.StorageServiceProperties; -import reactor.core.publisher.Mono; - import java.util.List; +import reactor.core.publisher.Mono; /** * An instance of this class provides access to all the operations defined in @@ -50,7 +51,7 @@ public final class ServicesImpl { * @param client the instance of the service client containing this operation class. */ public ServicesImpl(AzureQueueStorageImpl client) { - this.service = RestProxy.create(ServicesService.class, client); + this.service = RestProxy.create(ServicesService.class, client.httpPipeline()); this.client = client; } @@ -59,24 +60,24 @@ public ServicesImpl(AzureQueueStorageImpl client) { * proxy service to perform REST calls. */ @Host("{url}") - @Service("Storage Queues Services") + @ServiceInterface(name = "Services") private interface ServicesService { - @PUT("") + @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, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("restype") String restype, @QueryParam("comp") String comp, Context context); - @GET("") + @Get("") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono getProperties(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("restype") String restype, @QueryParam("comp") String comp, Context context); - @GET("") + @Get("") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono getStatistics(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("restype") String restype, @QueryParam("comp") String comp, Context context); - @GET("") + @Get("") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono listQueuesSegment(@HostParam("url") String url, @QueryParam("prefix") String prefix, @QueryParam("marker") String marker, @QueryParam("maxresults") Integer maxresults, @QueryParam("include") String include, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, Context context); @@ -90,6 +91,7 @@ private interface ServicesService { * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono setPropertiesWithRestResponseAsync(StorageServiceProperties storageServiceProperties, Context context) { final Integer timeout = null; final String requestId = null; @@ -108,6 +110,7 @@ public Mono setPropertiesWithRestResponseAsync(St * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono setPropertiesWithRestResponseAsync(StorageServiceProperties storageServiceProperties, Integer timeout, String requestId, Context context) { final String restype = "service"; final String comp = "properties"; @@ -121,6 +124,7 @@ public Mono setPropertiesWithRestResponseAsync(St * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getPropertiesWithRestResponseAsync(Context context) { final Integer timeout = null; final String requestId = null; @@ -138,6 +142,7 @@ public Mono getPropertiesWithRestResponseAsync(Co * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getPropertiesWithRestResponseAsync(Integer timeout, String requestId, Context context) { final String restype = "service"; final String comp = "properties"; @@ -151,6 +156,7 @@ public Mono getPropertiesWithRestResponseAsync(In * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getStatisticsWithRestResponseAsync(Context context) { final Integer timeout = null; final String requestId = null; @@ -168,6 +174,7 @@ public Mono getStatisticsWithRestResponseAsync(Co * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono getStatisticsWithRestResponseAsync(Integer timeout, String requestId, Context context) { final String restype = "service"; final String comp = "stats"; @@ -181,6 +188,7 @@ public Mono getStatisticsWithRestResponseAsync(In * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono listQueuesSegmentWithRestResponseAsync(Context context) { final String prefix = null; final String marker = null; @@ -205,6 +213,7 @@ public Mono listQueuesSegmentWithRestResponse * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ + @ServiceMethod(returns = ReturnType.SINGLE) public Mono listQueuesSegmentWithRestResponseAsync(String prefix, String marker, Integer maxresults, List include, Integer timeout, String requestId, Context context) { final String comp = "list"; String includeConverted = JacksonAdapter.createDefaultSerializerAdapter().serializeList(include, CollectionFormat.CSV); diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/AccessPolicy.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/AccessPolicy.java index e2a86de1dcbcd..40eec9949e94e 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/AccessPolicy.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/AccessPolicy.java @@ -4,6 +4,7 @@ package com.azure.storage.queue.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -12,6 +13,7 @@ * An Access policy. */ @JacksonXmlRootElement(localName = "AccessPolicy") +@Fluent public final class AccessPolicy { /* * the date-time the policy is active diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/CorsRule.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/CorsRule.java index e5836439cdf3e..ae40f253efb69 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/CorsRule.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/CorsRule.java @@ -4,6 +4,7 @@ package com.azure.storage.queue.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -15,6 +16,7 @@ * one domain (the origin domain) to call APIs in another domain. */ @JacksonXmlRootElement(localName = "CorsRule") +@Fluent public final class CorsRule { /* * The origin domains that are permitted to make a request against the diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/DequeuedMessage.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/DequeuedMessage.java new file mode 100644 index 0000000000000..81614fc1cba98 --- /dev/null +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/DequeuedMessage.java @@ -0,0 +1,235 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// Code generated by Microsoft (R) AutoRest Code Generator. + +package com.azure.storage.queue.models; + +import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; +import java.time.OffsetDateTime; + +/** + * The object returned in the QueueMessageList array when calling Get Messages + * on a Queue. + */ +@JacksonXmlRootElement(localName = "QueueMessage") +@Fluent +public final class DequeuedMessage { + /* + * The Id of the Message. + */ + @JsonProperty(value = "MessageId", required = true) + private String messageId; + + /* + * The time the Message was inserted into the Queue. + */ + @JsonProperty(value = "InsertionTime", required = true) + private DateTimeRfc1123 insertionTime; + + /* + * The time that the Message will expire and be automatically deleted. + */ + @JsonProperty(value = "ExpirationTime", required = true) + private DateTimeRfc1123 expirationTime; + + /* + * This value is required to delete the Message. If deletion fails using + * this popreceipt then the message has been dequeued by another client. + */ + @JsonProperty(value = "PopReceipt", required = true) + private String popReceipt; + + /* + * The time that the message will again become visible in the Queue. + */ + @JsonProperty(value = "TimeNextVisible", required = true) + private DateTimeRfc1123 timeNextVisible; + + /* + * The number of times the message has been dequeued. + */ + @JsonProperty(value = "DequeueCount", required = true) + private long dequeueCount; + + /* + * The content of the Message. + */ + @JsonProperty(value = "MessageText", required = true) + private String messageText; + + /** + * Get the messageId property: The Id of the Message. + * + * @return the messageId value. + */ + public String messageId() { + return this.messageId; + } + + /** + * Set the messageId property: The Id of the Message. + * + * @param messageId the messageId value to set. + * @return the DequeuedMessage object itself. + */ + public DequeuedMessage messageId(String messageId) { + this.messageId = messageId; + return this; + } + + /** + * Get the insertionTime property: The time the Message was inserted into + * the Queue. + * + * @return the insertionTime value. + */ + public OffsetDateTime insertionTime() { + if (this.insertionTime == null) { + return null; + } + return this.insertionTime.dateTime(); + } + + /** + * Set the insertionTime property: The time the Message was inserted into + * the Queue. + * + * @param insertionTime the insertionTime value to set. + * @return the DequeuedMessage object itself. + */ + public DequeuedMessage insertionTime(OffsetDateTime insertionTime) { + if (insertionTime == null) { + this.insertionTime = null; + } else { + this.insertionTime = new DateTimeRfc1123(insertionTime); + } + return this; + } + + /** + * Get the expirationTime property: The time that the Message will expire + * and be automatically deleted. + * + * @return the expirationTime value. + */ + public OffsetDateTime expirationTime() { + if (this.expirationTime == null) { + return null; + } + return this.expirationTime.dateTime(); + } + + /** + * Set the expirationTime property: The time that the Message will expire + * and be automatically deleted. + * + * @param expirationTime the expirationTime value to set. + * @return the DequeuedMessage object itself. + */ + public DequeuedMessage expirationTime(OffsetDateTime expirationTime) { + if (expirationTime == null) { + this.expirationTime = null; + } else { + this.expirationTime = new DateTimeRfc1123(expirationTime); + } + return this; + } + + /** + * Get the popReceipt property: This value is required to delete the + * Message. If deletion fails using this popreceipt then the message has + * been dequeued by another client. + * + * @return the popReceipt value. + */ + public String popReceipt() { + return this.popReceipt; + } + + /** + * Set the popReceipt property: This value is required to delete the + * Message. If deletion fails using this popreceipt then the message has + * been dequeued by another client. + * + * @param popReceipt the popReceipt value to set. + * @return the DequeuedMessage object itself. + */ + public DequeuedMessage popReceipt(String popReceipt) { + this.popReceipt = popReceipt; + return this; + } + + /** + * Get the timeNextVisible property: The time that the message will again + * become visible in the Queue. + * + * @return the timeNextVisible value. + */ + public OffsetDateTime timeNextVisible() { + if (this.timeNextVisible == null) { + return null; + } + return this.timeNextVisible.dateTime(); + } + + /** + * Set the timeNextVisible property: The time that the message will again + * become visible in the Queue. + * + * @param timeNextVisible the timeNextVisible value to set. + * @return the DequeuedMessage object itself. + */ + public DequeuedMessage timeNextVisible(OffsetDateTime timeNextVisible) { + if (timeNextVisible == null) { + this.timeNextVisible = null; + } else { + this.timeNextVisible = new DateTimeRfc1123(timeNextVisible); + } + return this; + } + + /** + * Get the dequeueCount property: The number of times the message has been + * dequeued. + * + * @return the dequeueCount value. + */ + public long dequeueCount() { + return this.dequeueCount; + } + + /** + * Set the dequeueCount property: The number of times the message has been + * dequeued. + * + * @param dequeueCount the dequeueCount value to set. + * @return the DequeuedMessage object itself. + */ + public DequeuedMessage dequeueCount(long dequeueCount) { + this.dequeueCount = dequeueCount; + return this; + } + + /** + * Get the messageText property: The content of the Message. + * + * @return the messageText value. + */ + public String messageText() { + return this.messageText; + } + + /** + * Set the messageText property: The content of the Message. + * + * @param messageText the messageText value to set. + * @return the DequeuedMessage object itself. + */ + public DequeuedMessage messageText(String messageText) { + this.messageText = messageText; + return this; + } +} diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/EnqueuedMessage.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/EnqueuedMessage.java index 16f1cccb9e244..096bbac70bdb3 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/EnqueuedMessage.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/EnqueuedMessage.java @@ -5,6 +5,7 @@ package com.azure.storage.queue.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -14,6 +15,7 @@ * on a Queue. */ @JacksonXmlRootElement(localName = "QueueMessage") +@Fluent public final class EnqueuedMessage { /* * The Id of the Message. diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/GeoReplication.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/GeoReplication.java index 1fc313b4a45b2..c6975aae93dc9 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/GeoReplication.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/GeoReplication.java @@ -5,6 +5,7 @@ package com.azure.storage.queue.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * The GeoReplication model. */ @JacksonXmlRootElement(localName = "GeoReplication") +@Fluent public final class GeoReplication { /* * The status of the secondary location. Possible values include: 'live', diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/ListQueuesSegmentResponse.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/ListQueuesSegmentResponse.java index 8e34bc50503ba..90d462272f47f 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/ListQueuesSegmentResponse.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/ListQueuesSegmentResponse.java @@ -4,6 +4,7 @@ package com.azure.storage.queue.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; @@ -15,6 +16,7 @@ * The object returned when calling List Queues on a Queue Service. */ @JacksonXmlRootElement(localName = "EnumerationResults") +@Fluent public final class ListQueuesSegmentResponse { /* * The serviceEndpoint property. diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/Logging.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/Logging.java index c5289b4fb5a50..a08399c0186c7 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/Logging.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/Logging.java @@ -4,6 +4,7 @@ package com.azure.storage.queue.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * Azure Analytics Logging settings. */ @JacksonXmlRootElement(localName = "Logging") +@Fluent public final class Logging { /* * The version of Storage Analytics to configure. diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessageIdDeleteHeaders.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessageIdDeleteHeaders.java index e369a4d60c99d..c51a8961f2bbc 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessageIdDeleteHeaders.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessageIdDeleteHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.queue.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for Delete operation. */ @JacksonXmlRootElement(localName = "MessageId-Delete-Headers") +@Fluent public final class MessageIdDeleteHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessageIdUpdateHeaders.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessageIdUpdateHeaders.java index a0129420618db..dba25a728e8ec 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessageIdUpdateHeaders.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessageIdUpdateHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.queue.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for Update operation. */ @JacksonXmlRootElement(localName = "MessageId-Update-Headers") +@Fluent public final class MessageIdUpdateHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesClearHeaders.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesClearHeaders.java index 6bb1165cb4de1..6265fda562731 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesClearHeaders.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesClearHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.queue.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for Clear operation. */ @JacksonXmlRootElement(localName = "Messages-Clear-Headers") +@Fluent public final class MessagesClearHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesDequeueHeaders.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesDequeueHeaders.java index 3957cd8a79d41..d9e8fd905f03e 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesDequeueHeaders.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesDequeueHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.queue.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for Dequeue operation. */ @JacksonXmlRootElement(localName = "Messages-Dequeue-Headers") +@Fluent public final class MessagesDequeueHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesDequeueResponse.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesDequeueResponse.java index 4ab4b09a4a620..c08c7ccc025c7 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesDequeueResponse.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesDequeueResponse.java @@ -12,7 +12,7 @@ /** * Contains all response data for the dequeue operation. */ -public final class MessagesDequeueResponse extends ResponseBase> { +public final class MessagesDequeueResponse extends ResponseBase> { /** * Creates an instance of MessagesDequeueResponse. * @@ -22,7 +22,7 @@ public final class MessagesDequeueResponse extends ResponseBase value, MessagesDequeueHeaders headers) { + public MessagesDequeueResponse(HttpRequest request, int statusCode, HttpHeaders rawHeaders, List value, MessagesDequeueHeaders headers) { super(request, statusCode, rawHeaders, value, headers); } @@ -30,7 +30,7 @@ public MessagesDequeueResponse(HttpRequest request, int statusCode, HttpHeaders * @return the deserialized response body. */ @Override - public List value() { + public List value() { return super.value(); } } diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesEnqueueHeaders.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesEnqueueHeaders.java index 39dc57ed0c2a1..d98604bb3c840 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesEnqueueHeaders.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesEnqueueHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.queue.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for Enqueue operation. */ @JacksonXmlRootElement(localName = "Messages-Enqueue-Headers") +@Fluent public final class MessagesEnqueueHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesPeekHeaders.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesPeekHeaders.java index 4733069112ace..fc4c65fcd5bd3 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesPeekHeaders.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesPeekHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.queue.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for Peek operation. */ @JacksonXmlRootElement(localName = "Messages-Peek-Headers") +@Fluent public final class MessagesPeekHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/Metrics.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/Metrics.java index 8c9b2fe7923ae..03a16a676ba14 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/Metrics.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/Metrics.java @@ -4,6 +4,7 @@ package com.azure.storage.queue.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * The Metrics model. */ @JacksonXmlRootElement(localName = "Metrics") +@Fluent public final class Metrics { /* * The version of Storage Analytics to configure. diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/PeekedMessageItem.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/PeekedMessageItem.java index d86bdab8c2305..c396a689dbaf2 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/PeekedMessageItem.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/PeekedMessageItem.java @@ -5,6 +5,7 @@ package com.azure.storage.queue.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -14,6 +15,7 @@ * on a Queue. */ @JacksonXmlRootElement(localName = "QueueMessage") +@Fluent public final class PeekedMessageItem { /* * The Id of the Message. diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueCreateHeaders.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueCreateHeaders.java index 7e0bee9cd7eb4..5feda5191d356 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueCreateHeaders.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueCreateHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.queue.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for Create operation. */ @JacksonXmlRootElement(localName = "Queue-Create-Headers") +@Fluent public final class QueueCreateHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueDeleteHeaders.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueDeleteHeaders.java index 5a29a098628c2..5d1db54847daa 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueDeleteHeaders.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueDeleteHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.queue.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for Delete operation. */ @JacksonXmlRootElement(localName = "Queue-Delete-Headers") +@Fluent public final class QueueDeleteHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueGetAccessPolicyHeaders.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueGetAccessPolicyHeaders.java index 65fa98edf8aa2..904ed5a98bca4 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueGetAccessPolicyHeaders.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueGetAccessPolicyHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.queue.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for GetAccessPolicy operation. */ @JacksonXmlRootElement(localName = "Queue-GetAccessPolicy-Headers") +@Fluent public final class QueueGetAccessPolicyHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueGetPropertiesHeaders.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueGetPropertiesHeaders.java index 20286e8a0ddb3..15d84b0192e7a 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueGetPropertiesHeaders.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueGetPropertiesHeaders.java @@ -4,8 +4,9 @@ package com.azure.storage.queue.models; -import com.azure.core.annotations.HeaderCollection; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; +import com.azure.core.implementation.annotation.HeaderCollection; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -15,6 +16,7 @@ * Defines headers for GetProperties operation. */ @JacksonXmlRootElement(localName = "Queue-GetProperties-Headers") +@Fluent public final class QueueGetPropertiesHeaders { /* * The metadata property. diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueItem.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueItem.java index 1575af6babcb8..ea9ca80c51004 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueItem.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueItem.java @@ -4,6 +4,7 @@ package com.azure.storage.queue.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.util.Map; @@ -12,6 +13,7 @@ * An Azure Storage Queue. */ @JacksonXmlRootElement(localName = "Queue") +@Fluent public final class QueueItem { /* * The name of the Queue. diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueMessage.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueMessage.java index 204825759ab0c..edd78cbfd5d35 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueMessage.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueMessage.java @@ -4,6 +4,7 @@ package com.azure.storage.queue.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * A Message object which can be stored in a Queue. */ @JacksonXmlRootElement(localName = "QueueMessage") +@Fluent public final class QueueMessage { /* * The content of the message diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueSetAccessPolicyHeaders.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueSetAccessPolicyHeaders.java index c2152ccc6a5cb..672543a78f1b2 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueSetAccessPolicyHeaders.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueSetAccessPolicyHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.queue.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for SetAccessPolicy operation. */ @JacksonXmlRootElement(localName = "Queue-SetAccessPolicy-Headers") +@Fluent public final class QueueSetAccessPolicyHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueSetMetadataHeaders.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueSetMetadataHeaders.java index f68e00835afaa..4c1997da6277b 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueSetMetadataHeaders.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueSetMetadataHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.queue.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for SetMetadata operation. */ @JacksonXmlRootElement(localName = "Queue-SetMetadata-Headers") +@Fluent public final class QueueSetMetadataHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/RetentionPolicy.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/RetentionPolicy.java index 045580d2c31ad..ada0ae8d0e2ca 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/RetentionPolicy.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/RetentionPolicy.java @@ -4,6 +4,7 @@ package com.azure.storage.queue.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * the retention policy. */ @JacksonXmlRootElement(localName = "RetentionPolicy") +@Fluent public final class RetentionPolicy { /* * Indicates whether a retention policy is enabled for the storage service diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/ServiceGetPropertiesHeaders.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/ServiceGetPropertiesHeaders.java index e58eab15aff92..5c099801501f6 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/ServiceGetPropertiesHeaders.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/ServiceGetPropertiesHeaders.java @@ -4,6 +4,7 @@ package com.azure.storage.queue.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * Defines headers for GetProperties operation. */ @JacksonXmlRootElement(localName = "Service-GetProperties-Headers") +@Fluent public final class ServiceGetPropertiesHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/ServiceGetStatisticsHeaders.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/ServiceGetStatisticsHeaders.java index ac56fc0624e8d..2dfaf92bbeaa5 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/ServiceGetStatisticsHeaders.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/ServiceGetStatisticsHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.queue.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for GetStatistics operation. */ @JacksonXmlRootElement(localName = "Service-GetStatistics-Headers") +@Fluent public final class ServiceGetStatisticsHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/ServiceListQueuesSegmentHeaders.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/ServiceListQueuesSegmentHeaders.java index 341fd32e50a97..8670be5637ce0 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/ServiceListQueuesSegmentHeaders.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/ServiceListQueuesSegmentHeaders.java @@ -5,6 +5,7 @@ package com.azure.storage.queue.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +14,7 @@ * Defines headers for ListQueuesSegment operation. */ @JacksonXmlRootElement(localName = "Service-ListQueuesSegment-Headers") +@Fluent public final class ServiceListQueuesSegmentHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/ServiceSetPropertiesHeaders.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/ServiceSetPropertiesHeaders.java index aa98c955afe48..6ae6da4ef69bf 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/ServiceSetPropertiesHeaders.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/ServiceSetPropertiesHeaders.java @@ -4,6 +4,7 @@ package com.azure.storage.queue.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * Defines headers for SetProperties operation. */ @JacksonXmlRootElement(localName = "Service-SetProperties-Headers") +@Fluent public final class ServiceSetPropertiesHeaders { /* * This header uniquely identifies the request that was made and can be diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/SignedIdentifier.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/SignedIdentifier.java index 7764f3a25ea75..56465abb7435c 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/SignedIdentifier.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/SignedIdentifier.java @@ -4,6 +4,7 @@ package com.azure.storage.queue.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * signed identifier. */ @JacksonXmlRootElement(localName = "SignedIdentifier") +@Fluent public final class SignedIdentifier { /* * a unique id diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/StorageError.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/StorageError.java index 0e264e6da0b82..b86ff0fd7e3fb 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/StorageError.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/StorageError.java @@ -4,6 +4,7 @@ package com.azure.storage.queue.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * The StorageError model. */ @JacksonXmlRootElement(localName = "StorageError") +@Fluent public final class StorageError { /* * The message property. diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/StorageServiceProperties.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/StorageServiceProperties.java index e13cbde9e5cfb..8a607a5a44943 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/StorageServiceProperties.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/StorageServiceProperties.java @@ -4,6 +4,7 @@ package com.azure.storage.queue.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; @@ -15,6 +16,7 @@ * Storage Service Properties. */ @JacksonXmlRootElement(localName = "StorageServiceProperties") +@Fluent public final class StorageServiceProperties { /* * Azure Analytics Logging settings diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/StorageServiceStats.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/StorageServiceStats.java index d70c794bda65a..6e45d422538f9 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/StorageServiceStats.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/StorageServiceStats.java @@ -4,6 +4,7 @@ package com.azure.storage.queue.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @@ -11,6 +12,7 @@ * Stats for the storage service. */ @JacksonXmlRootElement(localName = "StorageServiceStats") +@Fluent public final class StorageServiceStats { /* * Geo-Replication information for the Secondary Storage Service From b00cdc6af6df7c8fba03725bec110ecbbdc3f6f9 Mon Sep 17 00:00:00 2001 From: Alan Zimmer <48699787+alzimmermsft@users.noreply.github.com> Date: Fri, 19 Jul 2019 10:51:25 -0700 Subject: [PATCH 05/17] Add deleteContainer to StorageClient and getBlobClient with Snapshot to ContainerClient (#4376) * Removed raw clients * Added deleteContainer to StorageClient * Added getAppendBlob with snapshot to ContainerClient --- .../com/azure/storage/blob/BlobAsyncClient.java | 12 ++++-------- .../azure/storage/blob/ContainerAsyncClient.java | 6 ++---- .../com/azure/storage/blob/ContainerClient.java | 16 ++++++++++++++++ .../azure/storage/blob/StorageAsyncClient.java | 11 +++++++++++ .../com/azure/storage/blob/StorageClient.java | 11 +++++++++++ 5 files changed, 44 insertions(+), 12 deletions(-) diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobAsyncClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobAsyncClient.java index 2601107aaa0b6..c8ada7d8722fb 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobAsyncClient.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobAsyncClient.java @@ -194,8 +194,7 @@ public Mono> startCopyFromURL(URL sourceURL) { * @param destAccessConditions {@link BlobAccessConditions} against the destination. * @return A reactive response containing the copy ID for the long running operation. */ - public Mono> startCopyFromURL(URL sourceURL, Metadata metadata, - ModifiedAccessConditions sourceModifiedAccessConditions, BlobAccessConditions destAccessConditions) { + public Mono> startCopyFromURL(URL sourceURL, Metadata metadata, ModifiedAccessConditions sourceModifiedAccessConditions, BlobAccessConditions destAccessConditions) { metadata = metadata == null ? new Metadata() : metadata; sourceModifiedAccessConditions = sourceModifiedAccessConditions == null ? new ModifiedAccessConditions() : sourceModifiedAccessConditions; @@ -262,8 +261,7 @@ public Mono> copyFromURL(URL copySource) { * @param destAccessConditions {@link BlobAccessConditions} against the destination. * @return A reactive response containing the copy ID for the long running operation. */ - public Mono> copyFromURL(URL copySource, Metadata metadata, - ModifiedAccessConditions sourceModifiedAccessConditions, BlobAccessConditions destAccessConditions) { + public Mono> copyFromURL(URL copySource, Metadata metadata, ModifiedAccessConditions sourceModifiedAccessConditions, BlobAccessConditions destAccessConditions) { metadata = metadata == null ? new Metadata() : metadata; sourceModifiedAccessConditions = sourceModifiedAccessConditions == null ? new ModifiedAccessConditions() : sourceModifiedAccessConditions; @@ -302,8 +300,7 @@ public Mono>> download() { * @param options {@link ReliableDownloadOptions} * @return A reactive response containing the blob data. */ - public Mono>> download(BlobRange range, BlobAccessConditions accessConditions, - boolean rangeGetContentMD5, ReliableDownloadOptions options) { + public Mono>> download(BlobRange range, BlobAccessConditions accessConditions, boolean rangeGetContentMD5, ReliableDownloadOptions options) { return this.download(range, accessConditions, rangeGetContentMD5) .map(response -> new SimpleResponse<>( response.rawResponse(), @@ -457,8 +454,7 @@ public Mono delete() { * @param accessConditions {@link BlobAccessConditions} * @return A reactive response signalling completion. */ - public Mono delete(DeleteSnapshotsOptionType deleteBlobSnapshotOptions, - BlobAccessConditions accessConditions) { + public Mono delete(DeleteSnapshotsOptionType deleteBlobSnapshotOptions, BlobAccessConditions accessConditions) { accessConditions = accessConditions == null ? new BlobAccessConditions() : accessConditions; return postProcessResponse(this.azureBlobStorage.blobs().deleteWithRestResponseAsync( diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerAsyncClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerAsyncClient.java index 6d9e64f16a924..936bab6932528 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerAsyncClient.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerAsyncClient.java @@ -355,8 +355,7 @@ public Mono setMetadata(Metadata metadata) { * @throws UnsupportedOperationException If {@link ContainerAccessConditions#modifiedAccessConditions()} has * anything set other than {@link ModifiedAccessConditions#ifModifiedSince()}. */ - public Mono setMetadata(Metadata metadata, - ContainerAccessConditions accessConditions) { + public Mono setMetadata(Metadata metadata, ContainerAccessConditions accessConditions) { metadata = metadata == null ? new Metadata() : metadata; accessConditions = accessConditions == null ? new ContainerAccessConditions() : accessConditions; if (!validateNoEtag(accessConditions.modifiedAccessConditions()) @@ -434,8 +433,7 @@ public Mono setAccessPolicy(PublicAccessType accessType, * @throws UnsupportedOperationException If {@link ContainerAccessConditions#modifiedAccessConditions()} has either * {@link ModifiedAccessConditions#ifMatch()} or {@link ModifiedAccessConditions#ifNoneMatch()} set. */ - public Mono setAccessPolicy(PublicAccessType accessType, - List identifiers, ContainerAccessConditions accessConditions) { + public Mono setAccessPolicy(PublicAccessType accessType, List identifiers, ContainerAccessConditions accessConditions) { accessConditions = accessConditions == null ? new ContainerAccessConditions() : accessConditions; if (!validateNoEtag(accessConditions.modifiedAccessConditions())) { diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerClient.java index de5d4f1431f39..12d5844a696f4 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerClient.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerClient.java @@ -127,6 +127,22 @@ public AppendBlobClient getAppendBlobClient(String blobName) { return new AppendBlobClient(containerAsyncClient.getAppendBlobAsyncClient(blobName)); } + /** + * Creates creates a new AppendBlobClient object by concatenating blobName to the end of ContainerAsyncClient's URL. + * The new AppendBlobClient uses the same request policy pipeline as the ContainerAsyncClient. To change the + * pipeline, create the AppendBlobClient and then call its WithPipeline method passing in the desired pipeline + * object. Or, call this package's NewAppendBlobAsyncClient instead of calling this object's + * NewAppendBlobAsyncClient method. + * + * @param blobName A {@code String} representing the name of the blob. + * @param snapshot the snapshot identifier for the blob. + * @return A new {@link AppendBlobClient} object which references the blob with the specified name in this + * container. + */ + public AppendBlobClient getAppendBlobClient(String blobName, String snapshot) { + return new AppendBlobClient(containerAsyncClient.getAppendBlobAsyncClient(blobName, snapshot)); + } + /** * Initializes a new BlobClient object by concatenating blobName to the end of ContainerAsyncClient's URL. The new * BlobClient uses the same request policy pipeline as the ContainerAsyncClient. To change the pipeline, create the diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/StorageAsyncClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/StorageAsyncClient.java index b93ee7bd579e7..9e4d0fb2140f5 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/StorageAsyncClient.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/StorageAsyncClient.java @@ -106,6 +106,17 @@ public Mono> createContainer(String containerName .map(response -> new SimpleResponse<>(response, containerAsyncClient)); } + /** + * Deletes the specified container in the storage account. If the container doesn't exist the operation fails. For + * more information see the Azure Docs. + * + * @param containerName Name of the container to delete + * @return A response containing status code and HTTP headers + */ + public Mono deleteContainer(String containerName) { + return getContainerAsyncClient(containerName).delete(); + } + /** * Gets the URL of the storage account represented by this client. * diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/StorageClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/StorageClient.java index 1511726d653bb..5749b1b3fe7d7 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/StorageClient.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/StorageClient.java @@ -88,6 +88,17 @@ public Response createContainer(String containerName, Metadata return new SimpleResponse<>(client.create(metadata, accessType, null), client); } + /** + * Deletes the specified container in the storage account. If the container doesn't exist the operation fails. For + * more information see the Azure Docs. + * + * @param containerName Name of the container to delete + * @return A response containing status code and HTTP headers + */ + public VoidResponse deleteContainer(String containerName) { + return storageAsyncClient.deleteContainer(containerName).block(); + } + /** * Gets the URL of the storage account represented by this client. * From 78ea66bd8222df9d1ae6af68acfcf206286b7c16 Mon Sep 17 00:00:00 2001 From: Sima Zhu <48036328+sima-zhu@users.noreply.github.com> Date: Mon, 22 Jul 2019 09:23:56 -0700 Subject: [PATCH 06/17] Storage queue linting, builder refactor, tests (#4383) * Initial check in for storage queue --- .../resources/spotbugs/spotbugs-exclude.xml | 1 + eng/jacoco-test-coverage/pom.xml | 7 +- eng/spotbugs-aggregate-report/pom.xml | 7 +- pom.client.xml | 8 +- storage/client/queue/README.md | 135 ++-- storage/client/queue/pom.xml | 78 ++ .../credentials/SharedKeyCredential.java | 39 +- .../common/policy/RequestRetryOptions.java | 6 +- .../common/policy/RequestRetryPolicy.java | 4 + .../azure/storage/queue/QueueAsyncClient.java | 474 +++++++++++- .../queue/QueueAsyncClientBuilder.java | 5 - .../com/azure/storage/queue/QueueClient.java | 389 ++++++++++ .../storage/queue/QueueClientBuilder.java | 344 +++++++++ .../storage/queue/QueueConfiguration.java | 12 + .../queue/QueueServiceAsyncClient.java | 301 ++++++++ .../storage/queue/QueueServiceClient.java | 234 ++++++ .../queue/QueueServiceClientBuilder.java | 301 ++++++++ .../java/com/azure/storage/queue/README.md | 377 ++++++++++ .../AzureQueueStorageBuilder.java | 4 +- .../queue/implementation/MessageIdsImpl.java | 21 +- .../queue/implementation/MessagesImpl.java | 41 +- .../queue/implementation/QueuesImpl.java | 64 +- .../queue/implementation/ServicesImpl.java | 3 +- ...dMessageItem.java => DequeuedMessage.java} | 31 +- .../queue/models/MessagesDequeueResponse.java | 6 +- .../queue/models/MessagesPeekResponse.java | 6 +- ...kedMessageItem.java => PeekedMessage.java} | 23 +- .../storage/queue/models/QueueProperties.java | 38 + .../queue/models/QueuesSegmentOptions.java | 89 +++ .../storage/queue/models/UpdatedMessage.java | 39 + .../com/azure/storage/queue/package-info.java | 7 + .../com/azure/storage/queue/AsyncSamples.java | 42 ++ .../azure/storage/queue/MessageSamples.java | 73 ++ .../storage/queue/QueueExceptionSamples.java | 69 ++ .../storage/queue/QueueServiceSamples.java | 31 + .../com/azure/storage/queue/SampleHelper.java | 13 + .../javadoc/QueueJavaDocCodeSamples.java | 668 +++++++++++++++++ .../QueueServiceJavaDocCodeSamples.java | 369 ++++++++++ .../storage/queue/QueueAsyncClientTests.java | 695 ++++++++++++++++++ .../azure/storage/queue/QueueClientTests.java | 654 ++++++++++++++++ .../storage/queue/QueueClientTestsBase.java | 148 ++++ .../queue/QueueServiceAsyncClientTests.java | 250 +++++++ .../queue/QueueServiceClientTests.java | 257 +++++++ .../queue/QueueServiceClientTestsBase.java | 67 ++ .../com/azure/storage/queue/TestHelpers.java | 161 ++++ .../session-records/clearMessages.json | 161 ++++ .../clearMessagesQueueDoesNotExist.json | 42 ++ .../session-records/createQueue.json | 90 +++ .../createQueueTwiceDifferentMetadata.json | 90 +++ .../createQueueTwiceSameMetadata.json | 125 ++++ .../createQueueWithMetadata.json | 91 +++ .../createTwiceDifferentMetadata.json | 71 ++ .../createTwiceSameMetadata.json | 68 ++ .../session-records/createWithMetadata.json | 72 ++ .../session-records/createWithSASToken.json | 23 + .../session-records/createWithSharedKey.json | 23 + .../session-records/deleteExisting.json | 94 +++ .../session-records/deleteExistingQueue.json | 75 ++ .../session-records/deleteMessage.json | 124 ++++ .../deleteMessageInvalidMessageId.json | 109 +++ .../deleteMessageInvalidPopReceipt.json | 109 +++ .../deleteMessageQueueDoesNotExist.json | 42 ++ .../session-records/deleteMetadata.json | 106 +++ .../session-records/deleteNonExistent.json | 42 ++ .../deleteNonExistentQueue.json | 42 ++ .../session-records/dequeueMessage.json | 90 +++ .../dequeueMultipleMessages.json | 109 +++ .../dequeueQueueDoesNotExist.json | 42 ++ .../dequeueTooManyMessages.json | 71 ++ .../session-records/enqueueEmptyMessage.json | 90 +++ .../session-records/enqueueMessage.json | 90 +++ .../enqueueQueueDoesNotExist.json | 43 ++ .../enqueueShortTimeToLiveMessage.json | 90 +++ .../session-records/getAccessPolicy.json | 71 ++ .../getAccessPolicyQueueDoesNotExist.json | 42 ++ .../session-records/getProperties.json | 72 ++ .../getPropertiesQueueDoesNotExist.json | 42 ++ .../getQueueDoesNotCreateAQueue.json | 43 ++ .../resources/session-records/listQueues.json | 186 +++++ .../listQueuesIncludeMetadata.json | 186 +++++ .../session-records/listQueuesWithPrefix.json | 186 +++++ .../session-records/peekMessage.json | 90 +++ .../session-records/peekMultipleMessages.json | 109 +++ .../peekQueueDoesNotExist.json | 42 ++ .../session-records/peekTooManyMessages.json | 71 ++ .../session-records/setAccessPolicy.json | 88 +++ .../setAccessPolicyQueueDoesNotExist.json | 43 ++ .../setInvalidAccessPolicy.json | 72 ++ .../session-records/setInvalidMetadata.json | 71 ++ .../session-records/setMetadata.json | 88 +++ .../setMetadataQueueDoesNotExist.json | 42 ++ .../session-records/setProperties.json | 114 +++ .../setTooManyAccessPolicies.json | 72 ++ .../session-records/updateMessage.json | 128 ++++ .../updateMessageInvalidMessageId.json | 110 +++ .../updateMessageInvalidPopReceipt.json | 110 +++ .../updateMessageQueueDoesNotExist.json | 43 ++ 97 files changed, 10746 insertions(+), 190 deletions(-) create mode 100644 storage/client/queue/pom.xml delete mode 100644 storage/client/queue/src/main/java/com/azure/storage/queue/QueueAsyncClientBuilder.java create mode 100644 storage/client/queue/src/main/java/com/azure/storage/queue/QueueClient.java create mode 100644 storage/client/queue/src/main/java/com/azure/storage/queue/QueueClientBuilder.java create mode 100644 storage/client/queue/src/main/java/com/azure/storage/queue/QueueConfiguration.java create mode 100644 storage/client/queue/src/main/java/com/azure/storage/queue/QueueServiceAsyncClient.java create mode 100644 storage/client/queue/src/main/java/com/azure/storage/queue/QueueServiceClient.java create mode 100644 storage/client/queue/src/main/java/com/azure/storage/queue/QueueServiceClientBuilder.java create mode 100644 storage/client/queue/src/main/java/com/azure/storage/queue/README.md rename storage/client/queue/src/main/java/com/azure/storage/queue/models/{DequeuedMessageItem.java => DequeuedMessage.java} (85%) rename storage/client/queue/src/main/java/com/azure/storage/queue/models/{PeekedMessageItem.java => PeekedMessage.java} (85%) create mode 100644 storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueProperties.java create mode 100644 storage/client/queue/src/main/java/com/azure/storage/queue/models/QueuesSegmentOptions.java create mode 100644 storage/client/queue/src/main/java/com/azure/storage/queue/models/UpdatedMessage.java create mode 100644 storage/client/queue/src/main/java/com/azure/storage/queue/package-info.java create mode 100644 storage/client/queue/src/samples/java/com/azure/storage/queue/AsyncSamples.java create mode 100644 storage/client/queue/src/samples/java/com/azure/storage/queue/MessageSamples.java create mode 100644 storage/client/queue/src/samples/java/com/azure/storage/queue/QueueExceptionSamples.java create mode 100644 storage/client/queue/src/samples/java/com/azure/storage/queue/QueueServiceSamples.java create mode 100644 storage/client/queue/src/samples/java/com/azure/storage/queue/SampleHelper.java create mode 100644 storage/client/queue/src/samples/java/com/azure/storage/queue/javadoc/QueueJavaDocCodeSamples.java create mode 100644 storage/client/queue/src/samples/java/com/azure/storage/queue/javadoc/QueueServiceJavaDocCodeSamples.java create mode 100644 storage/client/queue/src/test/java/com/azure/storage/queue/QueueAsyncClientTests.java create mode 100644 storage/client/queue/src/test/java/com/azure/storage/queue/QueueClientTests.java create mode 100644 storage/client/queue/src/test/java/com/azure/storage/queue/QueueClientTestsBase.java create mode 100644 storage/client/queue/src/test/java/com/azure/storage/queue/QueueServiceAsyncClientTests.java create mode 100644 storage/client/queue/src/test/java/com/azure/storage/queue/QueueServiceClientTests.java create mode 100644 storage/client/queue/src/test/java/com/azure/storage/queue/QueueServiceClientTestsBase.java create mode 100644 storage/client/queue/src/test/java/com/azure/storage/queue/TestHelpers.java create mode 100644 storage/client/queue/src/test/resources/session-records/clearMessages.json create mode 100644 storage/client/queue/src/test/resources/session-records/clearMessagesQueueDoesNotExist.json create mode 100644 storage/client/queue/src/test/resources/session-records/createQueue.json create mode 100644 storage/client/queue/src/test/resources/session-records/createQueueTwiceDifferentMetadata.json create mode 100644 storage/client/queue/src/test/resources/session-records/createQueueTwiceSameMetadata.json create mode 100644 storage/client/queue/src/test/resources/session-records/createQueueWithMetadata.json create mode 100644 storage/client/queue/src/test/resources/session-records/createTwiceDifferentMetadata.json create mode 100644 storage/client/queue/src/test/resources/session-records/createTwiceSameMetadata.json create mode 100644 storage/client/queue/src/test/resources/session-records/createWithMetadata.json create mode 100644 storage/client/queue/src/test/resources/session-records/createWithSASToken.json create mode 100644 storage/client/queue/src/test/resources/session-records/createWithSharedKey.json create mode 100644 storage/client/queue/src/test/resources/session-records/deleteExisting.json create mode 100644 storage/client/queue/src/test/resources/session-records/deleteExistingQueue.json create mode 100644 storage/client/queue/src/test/resources/session-records/deleteMessage.json create mode 100644 storage/client/queue/src/test/resources/session-records/deleteMessageInvalidMessageId.json create mode 100644 storage/client/queue/src/test/resources/session-records/deleteMessageInvalidPopReceipt.json create mode 100644 storage/client/queue/src/test/resources/session-records/deleteMessageQueueDoesNotExist.json create mode 100644 storage/client/queue/src/test/resources/session-records/deleteMetadata.json create mode 100644 storage/client/queue/src/test/resources/session-records/deleteNonExistent.json create mode 100644 storage/client/queue/src/test/resources/session-records/deleteNonExistentQueue.json create mode 100644 storage/client/queue/src/test/resources/session-records/dequeueMessage.json create mode 100644 storage/client/queue/src/test/resources/session-records/dequeueMultipleMessages.json create mode 100644 storage/client/queue/src/test/resources/session-records/dequeueQueueDoesNotExist.json create mode 100644 storage/client/queue/src/test/resources/session-records/dequeueTooManyMessages.json create mode 100644 storage/client/queue/src/test/resources/session-records/enqueueEmptyMessage.json create mode 100644 storage/client/queue/src/test/resources/session-records/enqueueMessage.json create mode 100644 storage/client/queue/src/test/resources/session-records/enqueueQueueDoesNotExist.json create mode 100644 storage/client/queue/src/test/resources/session-records/enqueueShortTimeToLiveMessage.json create mode 100644 storage/client/queue/src/test/resources/session-records/getAccessPolicy.json create mode 100644 storage/client/queue/src/test/resources/session-records/getAccessPolicyQueueDoesNotExist.json create mode 100644 storage/client/queue/src/test/resources/session-records/getProperties.json create mode 100644 storage/client/queue/src/test/resources/session-records/getPropertiesQueueDoesNotExist.json create mode 100644 storage/client/queue/src/test/resources/session-records/getQueueDoesNotCreateAQueue.json create mode 100644 storage/client/queue/src/test/resources/session-records/listQueues.json create mode 100644 storage/client/queue/src/test/resources/session-records/listQueuesIncludeMetadata.json create mode 100644 storage/client/queue/src/test/resources/session-records/listQueuesWithPrefix.json create mode 100644 storage/client/queue/src/test/resources/session-records/peekMessage.json create mode 100644 storage/client/queue/src/test/resources/session-records/peekMultipleMessages.json create mode 100644 storage/client/queue/src/test/resources/session-records/peekQueueDoesNotExist.json create mode 100644 storage/client/queue/src/test/resources/session-records/peekTooManyMessages.json create mode 100644 storage/client/queue/src/test/resources/session-records/setAccessPolicy.json create mode 100644 storage/client/queue/src/test/resources/session-records/setAccessPolicyQueueDoesNotExist.json create mode 100644 storage/client/queue/src/test/resources/session-records/setInvalidAccessPolicy.json create mode 100644 storage/client/queue/src/test/resources/session-records/setInvalidMetadata.json create mode 100644 storage/client/queue/src/test/resources/session-records/setMetadata.json create mode 100644 storage/client/queue/src/test/resources/session-records/setMetadataQueueDoesNotExist.json create mode 100644 storage/client/queue/src/test/resources/session-records/setProperties.json create mode 100644 storage/client/queue/src/test/resources/session-records/setTooManyAccessPolicies.json create mode 100644 storage/client/queue/src/test/resources/session-records/updateMessage.json create mode 100644 storage/client/queue/src/test/resources/session-records/updateMessageInvalidMessageId.json create mode 100644 storage/client/queue/src/test/resources/session-records/updateMessageInvalidPopReceipt.json create mode 100644 storage/client/queue/src/test/resources/session-records/updateMessageQueueDoesNotExist.json 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 f7e3bcb5eb317..5f55e13d99146 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 @@ -439,6 +439,7 @@ + diff --git a/eng/jacoco-test-coverage/pom.xml b/eng/jacoco-test-coverage/pom.xml index ea21a08695cb7..cee087f22d298 100644 --- a/eng/jacoco-test-coverage/pom.xml +++ b/eng/jacoco-test-coverage/pom.xml @@ -32,6 +32,7 @@ 4.0.0-preview.1 5.0.0-preview.2 12.0.0-preview.1 + 12.0.0-preview.1 @@ -93,7 +94,11 @@ - + + com.azure + azure-storage-queue + ${azure-storage-queue.version} + diff --git a/eng/spotbugs-aggregate-report/pom.xml b/eng/spotbugs-aggregate-report/pom.xml index a8f5addab7e12..f390bb0c7db4c 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 @@ -182,7 +183,11 @@ - + + com.azure + azure-storage-queue + ${azure-storage-queue.version} + diff --git a/pom.client.xml b/pom.client.xml index d4ed7878ba447..e833ab1290e4e 100644 --- a/pom.client.xml +++ b/pom.client.xml @@ -393,6 +393,10 @@ Azure Storage - Blobs com.azure.storage.blob* + + Azure Storage - Queues + com.azure.storage.queue* + https://docs.oracle.com/javase/8/docs/api/ @@ -546,7 +550,8 @@ -snippetpath ${project.basedir}/sdk/eventhubs/azure-eventhubs/src/samples/java -snippetpath ${project.basedir}/sdk/keyvault/azure-keyvault-keys/src/samples/java -snippetpath ${project.basedir}/sdk/keyvault/azure-keyvault-secrets/src/samples/java - + + -snippetpath ${project.basedir}/storage/client/queue/src/samples/java @@ -748,5 +753,6 @@ ./sdk/identity/azure-identity ./storage/client/blob + ./storage/client/queue diff --git a/storage/client/queue/README.md b/storage/client/queue/README.md index 7b4dbbf1afadd..436f7e6f2094a 100644 --- a/storage/client/queue/README.md +++ b/storage/client/queue/README.md @@ -26,9 +26,7 @@ A single queue message can be up to 64 KB in size, and a queue can contain milli 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 +az group create --name storage-resource-group --location westus ``` ### Authenticate the client @@ -52,7 +50,6 @@ az storage queue generate-sas ```Powershell CONNECTION_STRING= -#usage example az storage queue generate-sas --name javasdksas --expiry 2019-06-05 @@ -112,10 +109,10 @@ The queue service do operations on the queues in the storage account and manage ### Queue Service Client The client performs the interactions with the Queue service, create or delete a queue, getting and setting Queue properties, list queues in account, and get queue statistics. An asynchronous, `QueueServiceAsyncClient`, and synchronous, `QueueClient`, client exists in the SDK allowing for selection of a client based on an application's use case. -Once you have the value of the SASToken you can create the queue service client with `${accountName}`, `${sasToken}`. +Once you have the value of the SASToken you can create the queue service client with `${accountName}`, `${SASToken}`. ```Java -String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", accountName, sasToken) -QueueServiceClient queueServiceClient = QueueServiceClient.builder().endpoint(queueURL).build(); +String queueServiceURL = String.format("https://%s.queue.core.windows.net", accountName) +QueueServiceClient queueServiceClient = new QueueServiceClientBuilder().endpoint(queueURL).credential(SASToken).build(); QueueClient newQueueServiceClient = queueServiceClient.createQueue("myqueue"); ``` @@ -123,8 +120,9 @@ QueueClient newQueueServiceClient = queueServiceClient.createQueue("myqueue"); or ```Java -String queueServiceAsyncURL = String.format("https://%s.queue.core.windows.net/%s", accountName, sasToken) -QueueServiceAsyncClient queueServiceAsyncClient = QueueServiceAsyncClient.builder().endpoint(queueServiceAsyncURL).build(); +String queueServiceAsyncURL = String.format("https://%s.queue.core.windows.net/", accountName) +QueueServiceAsyncClient queueServiceAsyncClient = new QueueServiceClientBuilder().endpoint(queueServiceAsyncURL) + credential(SASToken).build(); queueServiceAsyncClient.createQueue("newAsyncQueue").subscribe( result -> { // do something when new queue created @@ -142,10 +140,10 @@ Azure Queue storage is a service for storing large numbers of messages that can A single queue message can be up to 64 KB in size, and a queue can contain millions of messages, up to the total capacity limit of a storage account. ### QueueClient -Once you have the value of the SASToken you can create the queue service client with `${accountName}`, `${queueName}`, `${sasToken}`. +Once you have the value of the SASToken you can create the queue service client with `${accountName}`, `${queueName}`, `${SASToken}`. ```Java -String queueURL = String.format("https://%s.queue.core.windows.net/%s%s", accountName, queueName, sasToken); -QueueClient queueClient = QueueClient.builder().endpoint(queueURL).build(); +String queueURL = String.format("https://%s.queue.core.windows.net/%s", accountName, queueName); +QueueClient queueClient = QueueClient.builder().endpoint(queueURL).credential(SASToken).build(); // metadata is map of key-value pair, timeout is client side timeout QueueClient newQueueClient = queueClient.create(metadata, timeout); ``` @@ -170,6 +168,7 @@ queueAsyncClient.create(metadata, timeout).subscribe( ## Examples The following sections provide several code snippets covering some of the most common Configuration Service tasks, including: +- [Build a client](#build-a-client) - [Create a Queue](#Create-a-queue) - [Delete a queue](#Delete-a-queue) - [List the queues in account](#List-queues-in-account) @@ -183,32 +182,54 @@ The following sections provide several code snippets covering some of the most c - [Delete message from a queue](#Delete-message-from-a-queue) - [Get a Queue properties](#Get-a-queue-properties) - [Set/Update a Queue metadata](#Set-a-queue-metadata) + +### Build a client +We have two ways of building QueueService or Queue Client. Here will take queueServiceClient as an example. Same things apply to queueClient. + +First, build client from full URL/endpoint (e.g. with queueName, with SASToken and etc.) + +```Java +String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", accountName, sasToken); +QueueServiceClient queueServiceClient = new QueueServiceClientBuilder().endpoint(queueServiceURL).buildClient(); +``` + +Or + +We can build the queueServiceClient from the builder using `${SASToken}` as credential. + +```Java +String queueServiceURL = String.format("https://%s.queue.core.windows.net", accountName); +QueueServiceClient queueServiceClient = new QueueServiceClientBuilder().endpoint(queueServiceURL).credential(SASToken).buildClient(); +``` + ### Create a queue -Create a queue in the Storage Account. Throws StorageErrorException If the queue fails to be created. +Create a queue in the Storage Account using `${SASToken}` as credential. +Throws StorageErrorException If the queue fails to be created. ```Java -String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", accountName, sasToken) -QueueServiceClient queueServiceClient = QueueServiceClient.builder().endpoint(queueURL).build(); +String queueServiceURL = String.format("https://%s.queue.core.windows.net", accountName); +QueueServiceClient queueServiceClient = new QueueServiceClientBuilder().endpoint(queueServiceURL).credential(SASToken).buildClient(); QueueClient newQueueServiceClient = queueServiceClient.createQueue("myqueue"); ``` ### Delete a queue -Delete a queue in the Storage Account. Throws StorageErrorException If the queue fails to be deleted. +Delete a queue in the Storage Account using `${SASToken}` as credential. +Throws StorageErrorException If the queue fails to be deleted. ```Java -String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", accountName, sasToken) -QueueServiceClient queueServiceClient = QueueServiceClient.builder().endpoint(queueURL).build(); +String queueServiceURL = String.format("https://%s.queue.core.windows.net", accountName); +QueueServiceClient queueServiceClient = new QueueServiceClientBuilder().endpoint(queueServiceURL).credential(SASToken).buildClient(); QueueClient newQueueServiceClient = queueServiceClient.deleteQueue("myqueue"); ``` ### List queues in account -List all the queues in account. +List all the queues in account using `${SASToken}` as credential. ```Java -String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", accountName, sasToken) -QueueServiceClient queueServiceClient = QueueServiceClient.builder().endpoint(queueURL).build(); +String queueServiceURL = String.format("https://%s.queue.core.windows.net", accountName); +QueueServiceClient queueServiceClient = new QueueServiceClientBuilder().endpoint(queueServiceURL).credential(SASToken).buildClient(); // @param marker: Starting point to list the queues // @param options: Filter for queue selection queueServiceClient.listQueuesSegment(marker, options).forEach{ @@ -219,9 +240,11 @@ queueServiceClient.listQueuesSegment(marker, options).forEach{ ### Get properties in queue account Get queue properties in account, including properties for Storage Analytics and CORS (Cross-Origin Resource Sharing) rules. + +Use `${SASToken}` as credential. ```Java -String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", accountName, sasToken) -QueueServiceClient queueServiceClient = QueueServiceClient.builder().endpoint(queueURL).build(); +String queueServiceURL = String.format("https://%s.queue.core.windows.net", accountName); +QueueServiceClient queueServiceClient = new QueueServiceClientBuilder().endpoint(queueServiceURL).credential(SASToken).buildClient(); Response properties = queueServiceClient.getProperties(); ``` @@ -229,9 +252,11 @@ Response properties = queueServiceClient.getProperties ### Set properties in queue account Set queue properties in account, including properties for Storage Analytics and CORS (Cross-Origin Resource Sharing) rules. + +Use `${SASToken}` as credential. ```Java -String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", accountName, sasToken) -QueueServiceClient queueServiceClient = QueueServiceClient.builder().endpoint(queueURL).build(); +String queueServiceURL = String.format("https://%s.queue.core.windows.net", accountName); +QueueServiceClient queueServiceClient = new QueueServiceClientBuilder().endpoint(queueServiceURL).credential(SASToken).buildClient(); StorageServiceProperties properties = new StorageServiceProperties() { // logging: some logging; @@ -244,30 +269,34 @@ queueServiceClient.setProperties(properties); ``` ### Get queue service statistics -he `Get Queue Service Stats` operation retrieves statistics related to replication for the Queue service. +The `Get Queue Service Stats` operation retrieves statistics related to replication for the Queue service. + +Use `${SASToken}` as credential. It is only available on the secondary location endpoint when read-access geo-redundant replication is enabled for the storage account. ```Java -String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", accountName, sasToken) -QueueServiceClient queueServiceClient = QueueServiceClient.builder().endpoint(queueURL).build(); +String queueServiceURL = String.format("https://%s.queue.core.windows.net", accountName); +QueueServiceClient queueServiceClient = new QueueServiceClientBuilder().endpoint(queueServiceURL).credential(SASToken).buildClient(); Response queueStats = queueServiceClient.getStatistics(); ``` ### Enqueue message into a queue The operation adds a new message to the back of the message queue. A visibility timeout can also be specified to make the message invisible until the visibility timeout expires. + +Use `${SASToken}` as credential. A message must be in a format that can be included in an XML request with UTF-8 encoding. The encoded message can be up to 64 KB in size for versions 2011-08-18 and newer, or 8 KB in size for previous versions. ```Java -String queueURL = String.format("https://%s.queue.core.windows.net/%s%s", accountName, queueName, sasToken); -QueueClient queueClient = QueueClient.builder().endpoint(queueURL).build(); +String queueSURL = String.format("https://%s.queue.core.windows.net", accountName); +QueueClient queueClient = new QueueClientBuilder().endpoint(queueURL).credential(SASToken).queueName("myqueue").buildClient(); queueClient.enqueueMessage("myMessage"); ``` ### Update messaged from a queue -The operation updates a message in the message queue. +The operation updates a message in the message queue. Use `${SASToken}` as credential. ```Java -String queueURL = String.format("https://%s.queue.core.windows.net/%s%s", accountName, queueName, sasToken); -QueueClient queueClient = QueueClient.builder().endpoint(queueURL).build(); +String queueSURL = String.format("https://%s.queue.core.windows.net", accountName); +QueueClient queueClient = new QueueClientBuilder().endpoint(queueURL).credential(SASToken).queueName("myqueue").buildClient(); // @param messageId Id of the message // @param popReceipt Unique identifier that must match the message for it to be updated // @param visibilityTimeout How long the message will be invisible in the queue in seconds @@ -275,48 +304,52 @@ queueClient.updateMessage(messageId, "new message", popReceipt, visibilityTimeou ``` ### Peek messages from a queue -The operation retrieves one or more messages from the front of the queue. +The operation retrieves one or more messages from the front of the queue. Use `${SASToken}` as credential. ```Java -String queueURL = String.format("https://%s.queue.core.windows.net/%s%s", accountName, queueName, sasToken); -QueueClient queueClient = QueueClient.builder().endpoint(queueURL).build(); +String queueSURL = String.format("https://%s.queue.core.windows.net", accountName); +QueueClient queueClient = new QueueClientBuilder().endpoint(queueURL).credential(SASToken).queueName("myqueue").buildClient(); queueClient.peekMessages().forEach(message-> {print message.messageText();}); ``` ### Dequeue messages from a queue -The operation retrieves one or more messages from the front of the queue. +The operation retrieves one or more messages from the front of the queue. Use `${SASToken}` as credential. ```Java -String queueURL = String.format("https://%s.queue.core.windows.net/%s%s", accountName, queueName, sasToken); -QueueClient queueClient = QueueClient.builder().endpoint(queueURL).build(); +String queueSURL = String.format("https://%s.queue.core.windows.net", accountName); +QueueClient queueClient = new QueueClientBuilder().endpoint(queueURL).credential(SASToken).queueName("myqueue").buildClient(); queueClient.dequeueMessage("myMessage").forEach(message-> {print message.messageText();}); ``` ### Delete message from a queue -The operation retrieves one or more messages from the front of the queue. +The operation retrieves one or more messages from the front of the queue. Use `${SASToken}` as credential. ```Java -String queueURL = String.format("https://%s.queue.core.windows.net/%s%s", accountName, queueName, sasToken); -QueueClient queueClient = QueueClient.builder().endpoint(queueURL).build(); +String queueSURL = String.format("https://%s.queue.core.windows.net", accountName); +QueueClient queueClient = new QueueClientBuilder().endpoint(queueURL).credential(SASToken).queueName("myqueue").buildClient(); queueClient.deleteMessage(messageId, popReceipt); ``` ### Get a queue properties The operation retrieves user-defined metadata and queue properties on the specified queue. Metadata is associated with the queue as name-values pairs. + +Use `${SASToken}` as credential. ```Java -String queueURL = String.format("https://%s.queue.core.windows.net/%s%s", accountName, queueName, sasToken); -QueueClient queueClient = QueueClient.builder().endpoint(queueURL).build(); +String queueSURL = String.format("https://%s.queue.core.windows.net", accountName); +QueueClient queueClient = new QueueClientBuilder().endpoint(queueURL).credential(SASToken).queueName("myqueue").buildClient(); Response properties = queueClient.getProperties(); ``` ### Set a queue metadata The operation sets user-defined metadata on the specified queue. Metadata is associated with the queue as name-value pairs. + +Use `${SASToken}` as credential. ```Java -String queueURL = String.format("https://%s.queue.core.windows.net/%s%s", accountName, queueName, sasToken); -QueueClient queueClient = QueueClient.builder().endpoint(queueURL).build(); +String queueSURL = String.format("https://%s.queue.core.windows.net", accountName); +QueueClient queueClient = new QueueClientBuilder().endpoint(queueURL).credential(SASToken).queueName("myqueue").buildClient(); Map metadata = new HashMap<>() {{ put("key1", "val1"); @@ -335,10 +368,11 @@ When you interact with queue using this Java client library, errors returned by ## Next steps ### More Samples -- QueueServiceSample -- MessageSample -- QueueExceptionSample -- AsyncSample +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. [Quickstart: Create a Java Spring app with App Configuration](https://docs.microsoft.com/en-us/azure/azure-app-configuration/quickstart-java-spring-app) @@ -375,3 +409,4 @@ If you would like to become an active contributor to this project please follow [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 [storage_rest]: https://docs.microsoft.com/en-us/rest/api/storageservices/queue-service-error-codes +[samples]: samples/ diff --git a/storage/client/queue/pom.xml b/storage/client/queue/pom.xml new file mode 100644 index 0000000000000..c018da31ab260 --- /dev/null +++ b/storage/client/queue/pom.xml @@ -0,0 +1,78 @@ + + + + com.azure + azure-client-sdk-parent + 1.1.0 + ../../../pom.client.xml + + + 4.0.0 + + com.azure + azure-storage-queue + 12.0.0-preview.1 + + azure-storage-queue + 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 + + + org.slf4j + slf4j-api + + + + com.azure + azure-core-test + 1.0.0-preview.2 + test + + + com.azure + azure-identity + 1.0.0-preview.1 + test + + + junit + junit + test + + + org.slf4j + slf4j-simple + test + + + io.projectreactor + reactor-test + test + + + com.microsoft.azure + adal4j + test + + + diff --git a/storage/client/queue/src/main/java/com/azure/storage/common/credentials/SharedKeyCredential.java b/storage/client/queue/src/main/java/com/azure/storage/common/credentials/SharedKeyCredential.java index 19b2b4c307221..db8045e723a1a 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/common/credentials/SharedKeyCredential.java +++ b/storage/client/queue/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 static final ClientLogger LOGGER = new ClientLogger(SharedKeyCredential.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,11 @@ 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 +115,12 @@ 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) { + LOGGER.asError().log(e.getMessage()); + throw new RuntimeException(e); + } catch (InvalidKeyException e) { + LOGGER.asError().log("Please double check the account key. Error details: " + e.getMessage()); + throw new RuntimeException("Please double check the account key. Error details: " + e.getMessage()); } } @@ -121,20 +129,20 @@ private String buildStringToSign(URL requestURL, String httpMethod, MapSample 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) { @@ -105,7 +110,6 @@ public RequestRetryOptions(RetryPolicyType retryPolicyType, Integer maxTries, In } this.maxRetryDelayInMs = TimeUnit.SECONDS.toMillis(120); } - this.secondaryHost = secondaryHost; } diff --git a/storage/client/queue/src/main/java/com/azure/storage/common/policy/RequestRetryPolicy.java b/storage/client/queue/src/main/java/com/azure/storage/common/policy/RequestRetryPolicy.java index b862b76928af0..1b4bf56936bf5 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/common/policy/RequestRetryPolicy.java +++ b/storage/client/queue/src/main/java/com/azure/storage/common/policy/RequestRetryPolicy.java @@ -30,6 +30,10 @@ public final class RequestRetryPolicy implements HttpPipelinePolicy { private final RequestRetryOptions requestRetryOptions; + /** + * Create a policy of retrying a given HTTP request. + * @param requestRetryOptions Options for configuring the RequestRetryPolicy. + */ public RequestRetryPolicy(RequestRetryOptions requestRetryOptions) { this.requestRetryOptions = requestRetryOptions; } diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/QueueAsyncClient.java b/storage/client/queue/src/main/java/com/azure/storage/queue/QueueAsyncClient.java index eab2a19707d5c..2d3bd7636aeaf 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/QueueAsyncClient.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/QueueAsyncClient.java @@ -1,29 +1,473 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. package com.azure.storage.queue; -import com.azure.core.ServiceClient; 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.core.util.logging.ClientLogger; +import com.azure.storage.common.credentials.SASTokenCredential; +import com.azure.storage.common.credentials.SharedKeyCredential; import com.azure.storage.queue.implementation.AzureQueueStorageBuilder; import com.azure.storage.queue.implementation.AzureQueueStorageImpl; - +import com.azure.storage.queue.models.DequeuedMessage; +import com.azure.storage.queue.models.EnqueuedMessage; +import com.azure.storage.queue.models.MessageIdUpdateHeaders; +import com.azure.storage.queue.models.MessageIdsUpdateResponse; +import com.azure.storage.queue.models.PeekedMessage; +import com.azure.storage.queue.models.QueueGetPropertiesHeaders; +import com.azure.storage.queue.models.QueueMessage; +import com.azure.storage.queue.models.QueueProperties; +import com.azure.storage.queue.models.QueuesGetPropertiesResponse; +import com.azure.storage.queue.models.SignedIdentifier; +import com.azure.storage.queue.models.StorageErrorException; +import com.azure.storage.queue.models.UpdatedMessage; +import java.net.MalformedURLException; import java.net.URL; +import java.time.Duration; +import java.util.List; +import java.util.Map; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +/** + * This class provides a client that contains all the operations for interacting with a queue in Azure Storage Queue. + * Operations allowed by the client are creating and deleting the queue, retrieving and updating metadata and access + * policies of the queue, and enqueuing, dequeuing, peeking, updating, and deleting messages. + * + *

Instantiating an Asynchronous Queue Client

+ * + * {@codesnippet com.azure.storage.queue.queueAsyncClient.instantiation} + * + *

View {@link QueueClientBuilder this} for additional ways to construct the client.

+ * + * @see QueueClientBuilder + * @see QueueClient + * @see SharedKeyCredential + * @see SASTokenCredential + */ +public final class QueueAsyncClient { + private static final ClientLogger LOGGER = new ClientLogger(QueueAsyncClient.class); + private final AzureQueueStorageImpl client; + private final String queueName; + + /** + * Creates a QueueAsyncClient that sends requests to the storage queue service at {@code AzureQueueStorageImpl#url() endpoint}. + * Each service call goes through the {@link HttpPipeline pipeline} in the {@code AzureQueueStorageImpl client}. + * + * @param client Client that interacts with the service interfaces + * @param queueName Name of the queue + */ + QueueAsyncClient(AzureQueueStorageImpl client, String queueName) { + this.queueName = queueName; + + this.client = new AzureQueueStorageBuilder().pipeline(client.httpPipeline()) + .url(client.url()) + .version(client.version()) + .build(); + } + + /** + * Creates a QueueAsyncClient that sends requests to the storage queue service at {@code endpoint}. + * Each service call goes through the {@code httpPipeline}. + * + * @param endpoint URL for the Storage Queue service + * @param httpPipeline HttpPipeline that the HTTP requests and response flow through + * @param queueName Name of the queue + */ + QueueAsyncClient(URL endpoint, HttpPipeline httpPipeline, String queueName) { + this.queueName = queueName; + + this.client = new AzureQueueStorageBuilder().pipeline(httpPipeline) + .url(endpoint.toString()) + .build(); + } + + /** + * @return the URL of the storage queue + * @throws RuntimeException If the queue is using a malformed URL. + */ + public URL getQueueUrl() { + try { + return new URL(client.url()); + } catch (MalformedURLException ex) { + LOGGER.asError().log("Queue URL is malformed"); + throw new RuntimeException("Queue URL is malformed"); + } + } + + /** + * Creates a new queue. + * + *

Code Samples

+ * + *

Create a queue

+ * + * {@codesnippet com.azure.storage.queue.queueAsyncClient.create} + * + * @return A response that only contains headers and response status code + * @throws StorageErrorException If a queue with the same name already exists in the queue service. + */ + public Mono create() { + return create(null); + } + + /** + * Creates a new queue. + * + *

Code Samples

+ * + *

Create a queue with metadata "queue:metadataMap"

+ * + * {@codesnippet com.azure.storage.queue.queueAsyncClient.create#map} + * + * @param metadata Metadata to associate with the queue + * @return A response that only contains headers and response status code + * @throws StorageErrorException If a queue with the same name and different metadata already exists in the queue service. + */ + public Mono create(Map metadata) { + return client.queues().createWithRestResponseAsync(queueName, null, metadata, null, Context.NONE) + .map(VoidResponse::new); + } + + /** + * Permanently deletes the queue. + * + *

Code Samples

+ * + *

Delete a queue

+ * + * {@codesnippet com.azure.storage.queue.queueAsyncClient.delete} + * + * @return A response that only contains headers and response status code + * @throws StorageErrorException If the queue doesn't exist + */ + public Mono delete() { + return client.queues().deleteWithRestResponseAsync(queueName, Context.NONE) + .map(VoidResponse::new); + } + + /** + * Retrieves metadata and approximate message count of the queue. + * + *

Code Samples

+ * + *

Get the properties of the queue

+ * + * {@codesnippet com.azure.storage.queue.queueAsyncClient.getProperties} + * + * @return A response containing a {@link QueueProperties} value which contains the metadata and approximate + * messages count of the queue. + * @throws StorageErrorException If the queue doesn't exist + */ + public Mono> getProperties() { + return client.queues().getPropertiesWithRestResponseAsync(queueName, Context.NONE) + .map(this::getQueuePropertiesResponse); + } + + /** + * Sets the metadata of the queue. + * + * Passing in a {@code null} value for metadata will clear the metadata associated with the queue. + * + *

Code Samples

+ * + *

Set the queue's metadata to "queue:metadataMap"

+ * + * {@codesnippet com.azure.storage.queue.queueAsyncClient.setMetadata#map} + * + *

Clear the queue's metadata

+ * + * {@codesnippet com.azure.storage.queue.queueAsyncClient.clearMetadata#map} + * + * @param metadata Metadata to set on the queue + * @return A response that only contains headers and response status code + * @throws StorageErrorException If the queue doesn't exist + */ + public Mono setMetadata(Map metadata) { + return client.queues().setMetadataWithRestResponseAsync(queueName, null, metadata, null, Context.NONE) + .map(VoidResponse::new); + } + + /** + * Retrieves stored access policies specified on the queue. + * + *

Code Samples

+ * + *

List the stored access policies

+ * + * {@codesnippet com.azure.storage.queue.queueAsyncClient.getAccessPolicy} + * + * @return The stored access policies specified on the queue. + * @throws StorageErrorException If the queue doesn't exist + */ + public Flux getAccessPolicy() { + return client.queues().getAccessPolicyWithRestResponseAsync(queueName, Context.NONE) + .flatMapMany(response -> Flux.fromIterable(response.value())); + } + + /** + * Sets stored access policies on the queue. + * + *

Code Samples

+ * + *

Set a read only stored access policy

+ * + * {@codesnippet com.azure.storage.queue.queueAsyncClient.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 queue doesn't exist, a stored access policy doesn't have all fields filled out, + * or the queue will have more than five policies. + */ + public Mono setAccessPolicy(List permissions) { + return client.queues().setAccessPolicyWithRestResponseAsync(queueName, permissions, null, null, Context.NONE) + .map(VoidResponse::new); + } + + /** + * Deletes all messages in the queue. + * + *

Code Samples

+ * + *

Clear the messages

+ * + * {@codesnippet com.azure.storage.queue.queueAsyncClient.clearMessages} + * + * @return A response that only contains headers and response status code + * @throws StorageErrorException If the queue doesn't exist + */ + public Mono clearMessages() { + return client.messages().clearWithRestResponseAsync(queueName, Context.NONE) + .map(VoidResponse::new); + } + + /** + * Enqueues a message that has a time-to-live of 7 days and is instantly visible. + * + *

Code Samples

+ * + *

Enqueue a message of "Hello, Azure"

+ * + * {@codesnippet com.azure.storage.queue.queueAsyncClient.enqueueMessage#string} + * + * @param messageText Message text + * @return A {@link EnqueuedMessage} value that contains the {@link EnqueuedMessage#messageId() messageId} and + * {@link EnqueuedMessage#popReceipt() popReceipt} that are used to interact with the message and other metadata + * about the enqueued message. + * @throws StorageErrorException If the queue doesn't exist + */ + public Mono> enqueueMessage(String messageText) { + return enqueueMessage(messageText, Duration.ofSeconds(0), Duration.ofDays(7)); + } + + /** + * Enqueues a message with a given time-to-live and a timeout period where the message is invisible in the queue. + * + *

Code Samples

+ * + *

Add a message of "Hello, Azure" that has a timeout of 5 seconds

+ * + * {@codesnippet com.azure.storage.queue.queueAsyncClient.enqueueMessage#string-duration-duration} + * + *

Add a message of "Goodbye, Azure" that has a time to live of 5 seconds

+ * + * {@codesnippet com.azure.storage.queue.queueAsyncClient.enqueueMessageLiveTime#string-duration-duration} + * + * @param messageText Message text + * @param visibilityTimeout Optional. The timeout period for how long the message is invisible in the queue in seconds. + * If unset the value will default to 0 and the message will be instantly visible. The timeout must be between 0 + * seconds and 7 days. + * @param timeToLive Optional. How long the message will stay alive in the queue in seconds. If unset the value will + * default to 7 days, if -1 is passed the message will not expire. The time to live must be -1 or any positive number. + * @return A {@link EnqueuedMessage} value that contains the {@link EnqueuedMessage#messageId() messageId} and + * {@link EnqueuedMessage#popReceipt() popReceipt} that are used to interact with the message and other metadata + * about the enqueued message. + * @throws StorageErrorException If the queue doesn't exist or the {@code visibilityTimeout} or {@code timeToLive} + * are outside of the allowed limits. + */ + public Mono> enqueueMessage(String messageText, Duration visibilityTimeout, Duration timeToLive) { + Integer visibilityTimeoutInSeconds = (visibilityTimeout == null) ? null : (int) visibilityTimeout.getSeconds(); + Integer timeToLiveInSeconds = (timeToLive == null) ? null : (int) timeToLive.getSeconds(); + QueueMessage message = new QueueMessage().messageText(messageText); + + return client.messages().enqueueWithRestResponseAsync(queueName, message, visibilityTimeoutInSeconds, timeToLiveInSeconds, null, null, Context.NONE) + .map(response -> new SimpleResponse<>(response, response.value().get(0))); + } + + /** + * Retrieves the first message in the queue and hides it from other operations for 30 seconds. + * + *

Code Samples

+ * + *

Dequeue a message

+ * + * {@codesnippet com.azure.storage.queue.queueAsyncClient.dequeueMessages} + * + * @return The first {@link DequeuedMessage} in the queue, it contains + * {@link DequeuedMessage#messageId() messageId} and {@link DequeuedMessage#popReceipt() popReceipt} used to interact + * with the message, additionally it contains other metadata about the message. + * @throws StorageErrorException If the queue doesn't exist + */ + public Flux dequeueMessages() { + return dequeueMessages(1, Duration.ofSeconds(30)); + } + + /** + * Retrieves up to the maximum number of messages from the queue and hides them from other operations for 30 seconds. + * + *

Code Samples

+ * + *

Dequeue up to 5 messages

+ * + * {@codesnippet com.azure.storage.queue.queueAsyncClient.dequeueMessages#integer} + * + * @param maxMessages Optional. Maximum number of messages to get, if there are less messages exist in the queue than requested + * all the messages will be returned. If left empty only 1 message will be retrieved, the allowed range is 1 to 32 + * messages. + * @return Up to {@code maxMessages} {@link DequeuedMessage DequeuedMessages} from the queue. Each DequeuedMessage contains + * {@link DequeuedMessage#messageId() messageId} and {@link DequeuedMessage#popReceipt() popReceipt} used to interact + * with the message and other metadata about the message. + * @throws StorageErrorException If the queue doesn't exist or {@code maxMessages} is outside of the allowed bounds + */ + public Flux dequeueMessages(Integer maxMessages) { + return dequeueMessages(maxMessages, Duration.ofSeconds(30)); + } -public class QueueAsyncClient extends ServiceClient { - private final String endpoint; - private final AzureQueueStorageImpl generateClient; - private final String apiVersion; + /** + * Retrieves up to the maximum number of messages from the queue and hides them from other operations for the + * timeout period. + * + *

Code Samples

+ * + *

Dequeue up to 5 messages and give them a 60 second timeout period

+ * + * {@codesnippet com.azure.storage.queue.queueAsyncClient.dequeueMessages#integer-duration} + * + * @param maxMessages Optional. Maximum number of messages to get, if there are less messages exist in the queue than requested + * all the messages will be returned. If left empty only 1 message will be retrieved, the allowed range is 1 to 32 + * messages. + * @param visibilityTimeout Optional. The timeout period for how long the message is invisible in the queue in seconds. + * If left empty the dequeued messages will be invisible for 30 seconds. The timeout must be between 1 second and 7 days. + * @return Up to {@code maxMessages} {@link DequeuedMessage DequeuedMessages} from the queue. Each DeqeuedMessage contains + * {@link DequeuedMessage#messageId() messageId} and {@link DequeuedMessage#popReceipt() popReceipt} used to interact + * with the message and other metadata about the message. + * @throws StorageErrorException If the queue doesn't exist or {@code maxMessages} or {@code visibilityTimeout} is + * outside of the allowed bounds + */ + public Flux dequeueMessages(Integer maxMessages, Duration visibilityTimeout) { + Integer visibilityTimeoutInSeconds = (visibilityTimeout == null) ? null : (int) visibilityTimeout.getSeconds(); + return client.messages().dequeueWithRestResponseAsync(queueName, maxMessages, visibilityTimeoutInSeconds, null, null, Context.NONE) + .flatMapMany(response -> Flux.fromIterable(response.value())); + } - private QueueAsyncClient(URL endpoint, HttpPipeline httpPipeline) { - super(httpPipeline); - this.endpoint = endpoint.toString(); - this.generateClient = new AzureQueueStorageBuilder().pipeline(httpPipeline).url(this.endpoint).build(); - this.apiVersion = this.generateClient.version(); + /** + * Peeks the first message in the queue. + * + * Peeked messages don't contain the necessary information needed to interact with the message nor will it hide + * messages from other operations on the queue. + * + *

Code Samples

+ * + *

Peek the first message

+ * + * {@codesnippet com.azure.storage.queue.queueAsyncClient.peekMessages} + * + * @return A {@link PeekedMessage} that contains metadata about the message. + */ + public Flux peekMessages() { + return peekMessages(null); + } + + /** + * Peek messages from the front of the queue up to the maximum number of messages. + * + * Peeked messages don't contain the necessary information needed to interact with the message nor will it hide + * messages from other operations on the queue. + * + *

Code Samples

+ * + *

Peek up to the first five messages

+ * + * {@codesnippet com.azure.storage.queue.queueAsyncClient.peekMessages#integer} + * + * @param maxMessages Optional. Maximum number of messages to peek, if there are less messages exist in the queue than requested + * all the messages will be peeked. If left empty only 1 message will be peeked, the allowed range is 1 to 32 + * messages. + * @return Up to {@code maxMessages} {@link PeekedMessage PeekedMessages} from the queue. Each PeekedMessage contains + * metadata about the message. + * @throws StorageErrorException If the queue doesn't exist or {@code maxMessages} is outside of the allowed bounds + */ + public Flux peekMessages(Integer maxMessages) { + return client.messages().peekWithRestResponseAsync(queueName, maxMessages, null, null, Context.NONE) + .flatMapMany(response -> Flux.fromIterable(response.value())); } /** - * Creates a appendBlobClientBuilder that can configure options for the SecretAsyncClient before creating an instance of it. - * @return A new appendBlobClientBuilder to create a SecretAsyncClient from. + * Updates the specific message in the queue with a new message and resets the visibility timeout. + * + *

Code Samples

+ * + *

Dequeue the first message and update it to "Hello again, Azure" and hide it for 5 seconds

+ * + * {@codesnippet com.azure.storage.queue.queueAsyncClient.updateMessage} + * + * @param messageText Updated value for the message + * @param messageId Id of the message to update + * @param popReceipt Unique identifier that must match for the message to be updated + * @param visibilityTimeout The timeout period for how long the message is invisible in the queue in seconds. The + * timeout period must be between 1 second and 7 days. + * @return A {@link UpdatedMessage} that contains the new {@link UpdatedMessage#popReceipt() popReceipt} to interact + * with the message, additionally contains the updated metadata about the message. + * @throws StorageErrorException If the queue or messageId don't exist, the popReceipt doesn't match on the message, + * or the {@code visibilityTimeout} is outside the allowed bounds + */ + public Mono> updateMessage(String messageText, String messageId, String popReceipt, Duration visibilityTimeout) { + QueueMessage message = new QueueMessage().messageText(messageText); + return client.messageIds().updateWithRestResponseAsync(queueName, messageId, message, popReceipt, (int) visibilityTimeout.getSeconds(), Context.NONE) + .map(this::getUpdatedMessageResponse); + } + + /** + * Deletes the specified message in the queue + * + *

Code Samples

+ * + *

Delete the first message

+ * + * {@codesnippet com.azure.storage.queue.queueAsyncClient.deleteMessage} + * + * @param messageId Id of the message to deleted + * @param popReceipt Unique identifier that must match for the message to be deleted + * @return A response that only contains headers and response status code + * @throws StorageErrorException If the queue or messageId don't exist or the popReceipt doesn't match on the message + */ + public Mono deleteMessage(String messageId, String popReceipt) { + return client.messageIds().deleteWithRestResponseAsync(queueName, messageId, popReceipt, Context.NONE) + .map(VoidResponse::new); + } + + /* + * Maps the HTTP headers returned from the service to the expected response type + * @param response Service response + * @return Mapped response + */ + private Response getQueuePropertiesResponse(QueuesGetPropertiesResponse response) { + QueueGetPropertiesHeaders propertiesHeaders = response.deserializedHeaders(); + QueueProperties properties = new QueueProperties(propertiesHeaders.metadata(), propertiesHeaders.approximateMessagesCount()); + return new SimpleResponse<>(response, properties); + } + + /* + * Maps the HTTP headers returned from the service to the expected response type + * @param response Service response + * @return Mapped response */ - public static QueueAsyncClientBuilder builder() { - return new QueueAsyncClientBuilder(); + private Response getUpdatedMessageResponse(MessageIdsUpdateResponse response) { + MessageIdUpdateHeaders headers = response.deserializedHeaders(); + UpdatedMessage updatedMessage = new UpdatedMessage(headers.popReceipt(), headers.timeNextVisible()); + return new SimpleResponse<>(response, updatedMessage); } } diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/QueueAsyncClientBuilder.java b/storage/client/queue/src/main/java/com/azure/storage/queue/QueueAsyncClientBuilder.java deleted file mode 100644 index b76c9c63e8700..0000000000000 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/QueueAsyncClientBuilder.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.azure.storage.queue; - -public class QueueAsyncClientBuilder { - -} diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/QueueClient.java b/storage/client/queue/src/main/java/com/azure/storage/queue/QueueClient.java new file mode 100644 index 0000000000000..763c58560871e --- /dev/null +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/QueueClient.java @@ -0,0 +1,389 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.storage.queue; + +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.queue.models.DequeuedMessage; +import com.azure.storage.queue.models.EnqueuedMessage; +import com.azure.storage.queue.models.PeekedMessage; +import com.azure.storage.queue.models.QueueProperties; +import com.azure.storage.queue.models.SignedIdentifier; +import com.azure.storage.queue.models.StorageErrorException; +import com.azure.storage.queue.models.UpdatedMessage; +import java.net.URL; +import java.time.Duration; +import java.util.List; +import java.util.Map; + +/** + * This class provides a client that contains all the operations for interacting with a queue in Azure Storage Queue. + * Operations allowed by the client are creating and deleting the queue, retrieving and updating metadata and access + * policies of the queue, and enqueuing, dequeuing, peeking, updating, and deleting messages. + * + *

Instantiating an Synchronous Queue Client

+ * + * {@codesnippet com.azure.storage.queue.queueClient.instantiation} + * + *

View {@link QueueClientBuilder this} for additional ways to construct the client.

+ * + * @see QueueClientBuilder + * @see QueueAsyncClient + * @see SharedKeyCredential + * @see SASTokenCredential + */ +public final class QueueClient { + private final QueueAsyncClient client; + + /** + * Creates a QueueClient that wraps a QueueAsyncClient and blocks requests. + * + * @param client QueueAsyncClient that is used to send requests + */ + QueueClient(QueueAsyncClient client) { + this.client = client; + } + + /** + * @return the URL of the storage queue. + * @throws RuntimeException If the queue is using a malformed URL. + */ + public URL getQueueUrl() { + return client.getQueueUrl(); + } + + /** + * Creates a new queue. + * + *

Code Samples

+ * + *

Create a queue

+ * + *{@codesnippet com.azure.storage.queue.queueClient.create} + * + * @return A response that only contains headers and response status code + * @throws StorageErrorException If a queue with the same name already exists in the queue service. + */ + public VoidResponse create() { + return create(null); + } + + /** + * Creates a new queue. + * + *

Code Samples

+ * + *

Create a queue with metadata "queue:metadataMap"

+ * + * {@codesnippet com.azure.storage.queue.queueClient.create#map} + * + * @param metadata Metadata to associate with the queue + * @return A response that only contains headers and response status code + * @throws StorageErrorException If a queue with the same name and different metadata already exists in the queue service. + */ + public VoidResponse create(Map metadata) { + return client.create(metadata).block(); + } + + /** + * Permanently deletes the queue. + * + *

Code Samples

+ * + *

Delete a queue

+ * + * {@codesnippet com.azure.storage.queue.queueClient.delete} + * + * @return A response that only contains headers and response status code + * @throws StorageErrorException If the queue doesn't exist + */ + public VoidResponse delete() { + return client.delete().block(); + } + + /** + * Retrieves metadata and approximate message count of the queue. + * + *

Code Samples

+ * + *

Get the properties of the queue

+ * + * {@codesnippet com.azure.storage.queue.queueClient.getProperties} + * + * @return A response containing a {@link QueueProperties} value which contains the metadata and approximate + * messages count of the queue. + * @throws StorageErrorException If the queue doesn't exist + */ + public Response getProperties() { + return client.getProperties().block(); + } + + /** + * Sets the metadata of the queue. + * + * Passing in a {@code null} value for metadata will clear the metadata associated with the queue. + * + *

Code Samples

+ * + *

Set the queue's metadata to "queue:metadataMap"

+ * + * {@codesnippet com.azure.storage.queue.queueClient.setMetadata#map} + * + *

Clear the queue's metadata

+ * + * {@codesnippet com.azure.storage.queue.queueClient.clearMetadata#map} + * + * @param metadata Metadata to set on the queue + * @return A response that only contains headers and response status code + * @throws StorageErrorException If the queue doesn't exist + */ + public VoidResponse setMetadata(Map metadata) { + return client.setMetadata(metadata).block(); + } + + /** + * Retrieves stored access policies specified on the queue. + * + *

Code Samples

+ * + *

List the stored access policies

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

Code Samples

+ * + *

Set a read only stored access policy

+ * + * {@codesnippet com.azure.storage.queue.queueClient.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 queue doesn't exist, a stored access policy doesn't have all fields filled out, + * or the queue will have more than five policies. + */ + public VoidResponse setAccessPolicy(List permissions) { + return client.setAccessPolicy(permissions).block(); + } + + /** + * Deletes all messages in the queue. + * + *

Code Samples

+ * + *

Clear the messages

+ * + * {@codesnippet com.azure.storage.queue.queueClient.clearMessages} + * + * @return A response that only contains headers and response status code + * @throws StorageErrorException If the queue doesn't exist + */ + public VoidResponse clearMessages() { + return client.clearMessages().block(); + } + + /** + * Enqueues a message that has a time-to-live of 7 days and is instantly visible. + * + *

Code Samples

+ * + *

Enqueue a message of "Hello, Azure"

+ * + * {@codesnippet com.azure.storage.queue.queueClient.enqueueMessage#string} + * + * @param messageText Message text + * @return A {@link EnqueuedMessage} value that contains the {@link EnqueuedMessage#messageId() messageId} and + * {@link EnqueuedMessage#popReceipt() popReceipt} that are used to interact with the message and other metadata + * about the enqueued message. + * @throws StorageErrorException If the queue doesn't exist + */ + public Response enqueueMessage(String messageText) { + return enqueueMessage(messageText, Duration.ofSeconds(0), Duration.ofDays(7)); + } + + /** + * Enqueues a message with a given time-to-live and a timeout period where the message is invisible in the queue. + * + *

Code Samples

+ * + *

Add a message of "Hello, Azure" that has a timeout of 5 seconds

+ * + * {@codesnippet com.azure.storage.queue.queueClient.enqueueMessage#string-duration-duration} + * + *

Add a message of "Goodbye, Azure" that has a time to live of 5 seconds

+ * + * {@codesnippet com.azure.storage.queue.queueClient.enqueueMessageLiveTime#string-duration-duration} + * + * @param messageText Message text + * @param visibilityTimeout Optional. The timeout period for how long the message is invisible in the queue in seconds. + * If unset the value will default to 0 and the message will be instantly visible. The timeout must be between 0 + * seconds and 7 days. + * @param timeToLive Optional. How long the message will stay alive in the queue in seconds. If unset the value will + * default to 7 days, if -1 is passed the message will not expire. The time to live must be -1 or any positive number. + * @return A {@link EnqueuedMessage} value that contains the {@link EnqueuedMessage#messageId() messageId} and + * {@link EnqueuedMessage#popReceipt() popReceipt} that are used to interact with the message and other metadata + * about the enqueued message. + * @throws StorageErrorException If the queue doesn't exist or the {@code visibilityTimeout} or {@code timeToLive} + * are outside of the allowed limits. + */ + public Response enqueueMessage(String messageText, Duration visibilityTimeout, Duration timeToLive) { + return client.enqueueMessage(messageText, visibilityTimeout, timeToLive).block(); + } + + /** + * Retrieves the first message in the queue and hides it from other operations for 30 seconds. + * + *

Code Samples

+ * + *

Dequeue a message

+ * + * {@codesnippet com.azure.storage.queue.queueClient.dequeueMessages} + * + * @return The first {@link DequeuedMessage} in the queue, it contains + * {@link DequeuedMessage#messageId() messageId} and {@link DequeuedMessage#popReceipt() popReceipt} used to interact + * with the message, additionally it contains other metadata about the message. + * @throws StorageErrorException If the queue doesn't exist + */ + public Iterable dequeueMessages() { + return dequeueMessages(1, Duration.ofSeconds(30)); + } + + /** + * Retrieves up to the maximum number of messages from the queue and hides them from other operations for 30 seconds. + * + *

Code Samples

+ * + *

Dequeue up to 5 messages

+ * + * {@codesnippet com.azure.storage.queue.queueClient.dequeueMessages#integer} + * + * @param maxMessages Optional. Maximum number of messages to get, if there are less messages exist in the queue than requested + * all the messages will be returned. If left empty only 1 message will be retrieved, the allowed range is 1 to 32 + * messages. + * @return Up to {@code maxMessages} {@link DequeuedMessage DequeuedMessages} from the queue. Each DequeuedMessage contains + * {@link DequeuedMessage#messageId() messageId} and {@link DequeuedMessage#popReceipt() popReceipt} used to interact + * with the message and other metadata about the message. + * @throws StorageErrorException If the queue doesn't exist or {@code maxMessages} is outside of the allowed bounds + */ + public Iterable dequeueMessages(Integer maxMessages) { + return dequeueMessages(maxMessages, Duration.ofSeconds(30)); + } + + /** + * Retrieves up to the maximum number of messages from the queue and hides them from other operations for the + * timeout period. + * + *

Code Samples

+ * + *

Dequeue up to 5 messages and give them a 60 second timeout period

+ * + * {@codesnippet com.azure.storage.queue.queueClient.dequeueMessages#integer-duration} + * + * @param maxMessages Optional. Maximum number of messages to get, if there are less messages exist in the queue than requested + * all the messages will be returned. If left empty only 1 message will be retrieved, the allowed range is 1 to 32 + * messages. + * @param visibilityTimeout Optional. The timeout period for how long the message is invisible in the queue in seconds. + * If left empty the dequeued messages will be invisible for 30 seconds. The timeout must be between 1 second and 7 days. + * @return Up to {@code maxMessages} {@link DequeuedMessage DequeuedMessages} from the queue. Each DeqeuedMessage contains + * {@link DequeuedMessage#messageId() messageId} and {@link DequeuedMessage#popReceipt() popReceipt} used to interact + * with the message and other metadata about the message. + * @throws StorageErrorException If the queue doesn't exist or {@code maxMessages} or {@code visibilityTimeout} is + * outside of the allowed bounds + */ + public Iterable dequeueMessages(Integer maxMessages, Duration visibilityTimeout) { + return client.dequeueMessages(maxMessages, visibilityTimeout).toIterable(); + } + + /** + * Peeks the first message in the queue. + * + * Peeked messages don't contain the necessary information needed to interact with the message nor will it hide + * messages from other operations on the queue. + * + *

Code Samples

+ * + *

Peek the first message

+ * + * {@codesnippet com.azure.storage.queue.queueClient.peekMessages} + * + * @return A {@link PeekedMessage} that contains metadata about the message. + */ + public Iterable peekMessages() { + return peekMessages(null); + } + + /** + * Peek messages from the front of the queue up to the maximum number of messages. + * + * Peeked messages don't contain the necessary information needed to interact with the message nor will it hide + * messages from other operations on the queue. + * + *

Code Samples

+ * + *

Peek up to the first five messages

+ * + * {@codesnippet com.azure.storage.queue.queueClient.peekMessages#integer} + * + * @param maxMessages Optional. Maximum number of messages to peek, if there are less messages exist in the queue than requested + * all the messages will be peeked. If left empty only 1 message will be peeked, the allowed range is 1 to 32 + * messages. + * @return Up to {@code maxMessages} {@link PeekedMessage PeekedMessages} from the queue. Each PeekedMessage contains + * metadata about the message. + * @throws StorageErrorException If the queue doesn't exist or {@code maxMessages} is outside of the allowed bounds + */ + public Iterable peekMessages(Integer maxMessages) { + return client.peekMessages(maxMessages).toIterable(); + } + + /** + * Updates the specific message in the queue with a new message and resets the visibility timeout. + * + *

Code Samples

+ * + *

Dequeue the first message and update it to "Hello again, Azure" and hide it for 5 seconds

+ * + * {@codesnippet com.azure.storage.queue.queueClient.updateMessage} + * + * @param messageText Updated value for the message + * @param messageId Id of the message to update + * @param popReceipt Unique identifier that must match for the message to be updated + * @param visibilityTimeout The timeout period for how long the message is invisible in the queue in seconds. The + * timeout period must be between 1 second and 7 days. + * @return A {@link UpdatedMessage} that contains the new {@link UpdatedMessage#popReceipt() popReceipt} to interact + * with the message, additionally contains the updated metadata about the message. + * @throws StorageErrorException If the queue or messageId don't exist, the popReceipt doesn't match on the message, + * or the {@code visibilityTimeout} is outside the allowed bounds + */ + public Response updateMessage(String messageText, String messageId, String popReceipt, Duration visibilityTimeout) { + return client.updateMessage(messageText, messageId, popReceipt, visibilityTimeout).block(); + } + + /** + * Deletes the specified message in the queue + * + *

Code Samples

+ * + *

Delete the first message

+ * + * {@codesnippet com.azure.storage.queue.queueClient.deleteMessage} + * + * @param messageId Id of the message to deleted + * @param popReceipt Unique identifier that must match for the message to be deleted + * @return A response that only contains headers and response status code + * @throws StorageErrorException If the queue or messageId don't exist or the popReceipt doesn't match on the message + */ + public VoidResponse deleteMessage(String messageId, String popReceipt) { + return client.deleteMessage(messageId, popReceipt).block(); + } +} diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/QueueClientBuilder.java b/storage/client/queue/src/main/java/com/azure/storage/queue/QueueClientBuilder.java new file mode 100644 index 0000000000000..d272cfc1bbf89 --- /dev/null +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/QueueClientBuilder.java @@ -0,0 +1,344 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.storage.queue; + +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.implementation.util.ImplUtils; +import com.azure.core.util.configuration.Configuration; +import com.azure.core.util.configuration.ConfigurationManager; +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.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.Objects; + +/** + * This class provides a fluent builder API to help aid the configuration and instantiation of the {@link QueueClient QueueClients} + * and {@link QueueAsyncClient QueueAsyncClients}, calling {@link QueueClientBuilder#buildClient() buildClient} constructs an + * instance of QueueClient and calling {@link QueueClientBuilder#buildAsyncClient() buildAsyncClient} constructs an instance of + * QueueAsyncClient. + * + *

The client needs the endpoint of the Azure Storage Queue service, name of the queue, and authorization credentials. + * {@link QueueClientBuilder#endpoint(String) endpoint} gives the builder the endpoint and may give the builder the + * {@link QueueClientBuilder#queueName(String) queueName} and a {@link SASTokenCredential} that authorizes the client.

+ * + *

Instantiating a synchronous Queue Client with SAS token

+ * {@codesnippet com.azure.storage.queue.queueClient.instantiation.sastoken} + * + *

Instantiating an Asynchronous Queue Client with SAS token

+ * {@codesnippet com.azure.storage.queue.queueAsyncClient.instantiation.sastoken} + * + *

If the {@code endpoint} doesn't contain the queue name or {@code SASTokenCredential} they may be set using + * {@link QueueClientBuilder#queueName(String) queueName} and {@link QueueClientBuilder#credential(SASTokenCredential) credential}.

+ * + *

Instantiating a synchronous Queue Client with credential

+ * {@codesnippet com.azure.storage.queue.queueClient.instantiation.credential} + * + *

Instantiating an Asynchronous Queue Client with credential

+ * {@codesnippet com.azure.storage.queue.queueAsyncClient.instantiation.credential} + * + *

Another way to authenticate the client is using a {@link SharedKeyCredential}. To create a SharedKeyCredential + * a connection string from the Storage Queue service must be used. Set the SharedKeyCredential with + * {@link QueueClientBuilder#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 Queue Client with connection string.

+ * {@codesnippet com.azure.storage.queue.queueClient.instantiation.connectionstring} + * + *

Instantiating an Asynchronous Queue Client with connection string.

+ * {@codesnippet com.azure.storage.queue.queueAsyncClient.instantiation.connectionstring} + * + * @see QueueClient + * @see QueueAsyncClient + * @see SASTokenCredential + * @see SharedKeyCredential + */ +public final class QueueClientBuilder { + private static final ClientLogger LOGGER = new ClientLogger(QueueClientBuilder.class); + private static final String ACCOUNT_NAME = "accountname"; + private final List policies; + + private URL endpoint; + private String queueName; + 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 QueueClient QueueClients} + * and {@link QueueAsyncClient QueueAsyncClients}. + */ + public QueueClientBuilder() { + retryPolicy = new RetryPolicy(); + logLevel = HttpLogDetailLevel.NONE; + policies = new ArrayList<>(); + + configuration = ConfigurationManager.getConfiguration(); + } + + /** + * Creates a {@link QueueClient} based on options set in the builder. Every time {@code buildClient()} is + * called a new instance of {@link QueueClient} is created. + * + *

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

+ * + * @return A QueueClient with the options set from the builder. + * @throws NullPointerException If {@code endpoint} or {@code queueName} have not been set. + * @throws IllegalStateException If neither a {@link SharedKeyCredential} or {@link SASTokenCredential} has been set. + */ + public QueueClient buildClient() { + return new QueueClient(buildAsyncClient()); + } + + /** + * Creates a {@link QueueAsyncClient} based on options set in the builder. Every time {@code buildAsyncClient()} is + * called a new instance of {@link QueueAsyncClient} is created. + * + *

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

+ * + * @return A QueueAsyncClient with the options set from the builder. + * @throws NullPointerException If {@code endpoint} or {@code queueName} have not been set. + * @throws IllegalArgumentException If neither a {@link SharedKeyCredential} or {@link SASTokenCredential} has been set. + */ + public QueueAsyncClient buildAsyncClient() { + Objects.requireNonNull(endpoint); + Objects.requireNonNull(queueName); + + if (sasTokenCredential == null && sharedKeyCredential == null) { + LOGGER.asError().log("Credentials are required for authorization"); + throw new IllegalArgumentException("Credentials are required for authorization"); + } + + if (pipeline != null) { + return new QueueAsyncClient(endpoint, pipeline, queueName); + } + // Closest to API goes first, closest to wire goes last. + final List policies = new ArrayList<>(); + + policies.add(new UserAgentPolicy(QueueConfiguration.NAME, QueueConfiguration.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 QueueAsyncClient(endpoint, pipeline, queueName); + } + + /** + * Sets the endpoint for the Azure Storage Queue 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 queue + * 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 Queue instance to send service requests to and receive responses from. + * @return the updated QueueClientBuilder object + * @throws IllegalArgumentException If {@code endpoint} isn't a proper URL + */ + public QueueClientBuilder endpoint(String endpoint) { + Objects.requireNonNull(endpoint); + try { + URL fullURL = new URL(endpoint); + this.endpoint = new URL(fullURL.getProtocol() + "://" + fullURL.getHost()); + + // Attempt to get the queue name from the URL passed + String[] pathSegments = fullURL.getPath().split("/", 2); + if (pathSegments.length == 2 && !ImplUtils.isNullOrEmpty(pathSegments[1])) { + this.queueName = pathSegments[1]; + } + + // Attempt to get the SAS token from the URL passed + SASTokenCredential credential = SASTokenCredential.fromQuery(fullURL.getQuery()); + if (credential != null) { + this.sasTokenCredential = credential; + } + } catch (MalformedURLException ex) { + LOGGER.asError().log("The Azure Storage Queue endpoint url is malformed. Endpoint: " + endpoint); + throw new IllegalArgumentException("The Azure Storage Queue endpoint url is malformed. Endpoint: " + endpoint); + } + + return this; + } + + /** + * Sets the name of the queue that the client will interact with. + * + * @param queueName Name of the queue + * @return the updated QueueClientBuilder object + * @throws NullPointerException If {@code queueName} is {@code null}. + */ + public QueueClientBuilder queueName(String queueName) { + this.queueName = Objects.requireNonNull(queueName); + return this; + } + + /** + * Sets the {@link SASTokenCredential} used to authenticate requests sent to the Queue. + * + * @param credential SAS token credential generated from the Storage account that authorizes requests + * @return the updated QueueClientBuilder object + * @throws NullPointerException If {@code credential} is {@code null}. + */ + public QueueClientBuilder credential(SASTokenCredential credential) { + this.sasTokenCredential = Objects.requireNonNull(credential); + return this; + } + + /** + * Sets the {@link SharedKeyCredential} used to authenticate requests sent to the Queue. + * + * @param credential Shared key credential can retrieve from the Storage account that authorizes requests + * @return the updated QueueServiceClientBuilder object + * @throws NullPointerException If {@code credential} is {@code null}. + */ + public QueueClientBuilder credential(SharedKeyCredential credential) { + this.sharedKeyCredential = Objects.requireNonNull(credential); + return this; + } + + /** + * Creates a {@link SharedKeyCredential} from the {@code connectionString} used to authenticate requests sent to the + * Queue service. + * + * @param connectionString Connection string from the Access Keys section in the Storage account + * @return the updated QueueClientBuilder object + * @throws NullPointerException If {@code connectionString} is {@code null}. + */ + public QueueClientBuilder connectionString(String connectionString) { + Objects.requireNonNull(connectionString); + this.sharedKeyCredential = SharedKeyCredential.fromConnectionString(connectionString); + getEndPointFromConnectionString(connectionString); + return this; + } + + private void getEndPointFromConnectionString(String connectionString) { + HashMap 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.queue.core.windows.net", accountName)); + } catch (MalformedURLException e) { + LOGGER.asError().log("There is no valid account for the connection string. " + + "Connection String: %s", connectionString); + throw new IllegalArgumentException(String.format("There is no valid account 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 QueueClientBuilder object. + * @throws NullPointerException If {@code httpClient} is {@code null}. + */ + public QueueClientBuilder 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 QueueClientBuilder object. + * @throws NullPointerException If {@code pipelinePolicy} is {@code null}. + */ + public QueueClientBuilder 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 QueueClientBuilder object. + */ + public QueueClientBuilder 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 QueueClientBuilder#endpoint(String) endpoint} + * and {@link QueueClientBuilder#queueName(String) queueName} when building clients. + * + * @param pipeline The HTTP pipeline to use for sending service requests and receiving responses. + * @return The updated QueueClientBuilder object. + * @throws NullPointerException If {@code pipeline} is {@code null}. + */ + public QueueClientBuilder pipeline(HttpPipeline pipeline) { + Objects.requireNonNull(pipeline); + this.pipeline = 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 QueueClientBuilder object. + */ + public QueueClientBuilder configuration(Configuration configuration) { + this.configuration = configuration; + return this; + } +} diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/QueueConfiguration.java b/storage/client/queue/src/main/java/com/azure/storage/queue/QueueConfiguration.java new file mode 100644 index 0000000000000..7a794525484f7 --- /dev/null +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/QueueConfiguration.java @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.storage.queue; + +/* + * Gets the SDK information for this library component. + */ +class QueueConfiguration { + //TODO: Eventually remove these hardcoded strings with https://github.com/Azure/azure-sdk-for-java/issues/3141 + static final String NAME = "azure-storage-queue"; + static final String VERSION = "12.0.0-preview.1"; +} diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/QueueServiceAsyncClient.java b/storage/client/queue/src/main/java/com/azure/storage/queue/QueueServiceAsyncClient.java new file mode 100644 index 0000000000000..e093f1d34b171 --- /dev/null +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/QueueServiceAsyncClient.java @@ -0,0 +1,301 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.storage.queue; + +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.core.util.logging.ClientLogger; +import com.azure.storage.common.credentials.SASTokenCredential; +import com.azure.storage.common.credentials.SharedKeyCredential; +import com.azure.storage.queue.implementation.AzureQueueStorageBuilder; +import com.azure.storage.queue.implementation.AzureQueueStorageImpl; +import com.azure.storage.queue.models.CorsRule; +import com.azure.storage.queue.models.ListQueuesIncludeType; +import com.azure.storage.queue.models.ListQueuesSegmentResponse; +import com.azure.storage.queue.models.QueueItem; +import com.azure.storage.queue.models.QueuesSegmentOptions; +import com.azure.storage.queue.models.ServicesListQueuesSegmentResponse; +import com.azure.storage.queue.models.StorageErrorException; +import com.azure.storage.queue.models.StorageServiceProperties; +import com.azure.storage.queue.models.StorageServiceStats; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +/** + * This class provides a client that contains all the operations for interacting with a queue account in Azure Storage. + * Operations allowed by the client are creating, listing, and deleting queues, retrieving and updating properties of the account, + * and retrieving statistics of the account. + * + *

Instantiating an Asynchronous Queue Service Client

+ * + * {@codesnippet com.azure.storage.queue.queueServiceAsyncClient.instantiation} + * + *

View {@link QueueServiceClientBuilder this} for additional ways to construct the client.

+ * + * @see QueueServiceClientBuilder + * @see QueueServiceClient + * @see SharedKeyCredential + * @see SASTokenCredential + */ +public final class QueueServiceAsyncClient { + private static final ClientLogger LOGGER = new ClientLogger(QueueServiceAsyncClient.class); + private final AzureQueueStorageImpl client; + + /** + * Creates a QueueServiceAsyncClient that sends requests to the storage account at {@code endpoint}. + * Each service call goes through the {@code httpPipeline}. + * + * @param endpoint URL for the Storage Queue service + * @param httpPipeline HttpPipeline that the HTTP requests and response flow through + */ + QueueServiceAsyncClient(URL endpoint, HttpPipeline httpPipeline) { + this.client = new AzureQueueStorageBuilder().pipeline(httpPipeline) + .url(endpoint.toString()) + .build(); + } + + /** + * @return the URL of the storage queue + * @throws RuntimeException If the queue service is using a malformed URL. + */ + public URL getQueueServiceUrl() { + try { + return new URL(client.url()); + } catch (MalformedURLException ex) { + LOGGER.asError().log("Queue Service URL is malformed"); + throw new RuntimeException("Storage account URL is malformed"); + } + } + + /** + * Constructs a QueueAsyncClient that interacts with the specified queue. + * + * This will not create the queue in the storage account if it doesn't exist. + * + * @param queueName Name of the queue + * @return QueueAsyncClient that interacts with the specified queue + */ + public QueueAsyncClient getQueueAsyncClient(String queueName) { + return new QueueAsyncClient(client, queueName); + } + + /** + * Creates a queue in the storage account with the specified name and returns a QueueAsyncClient to interact + * with it. + * + *

Code Samples

+ * + *

Create the queue "test"

+ * + * {@codesnippet com.azure.storage.queue.queueServiceAsyncClient.createQueue#string} + * + * @param queueName Name of the queue + * @return A response containing the QueueAsyncClient and the status of creating the queue + * @throws StorageErrorException If a queue with the same name and different metadata already exists + */ + public Mono> createQueue(String queueName) { + return createQueue(queueName, null); + } + + /** + * Creates a queue in the storage account with the specified name and metadata and returns a QueueAsyncClient to + * interact with it. + * + *

Code Samples

+ * + *

Create the queue "test" with metadata "queue:metadata"

+ * + * {@codesnippet com.azure.storage.queue.queueServiceAsyncClient.createQueue#string-map} + * + * @param queueName Name of the queue + * @param metadata Metadata to associate with the queue + * @return A response containing the QueueAsyncClient and the status of creating the queue + * @throws StorageErrorException If a queue with the same name and different metadata already exists + */ + public Mono> createQueue(String queueName, Map metadata) { + QueueAsyncClient queueAsyncClient = new QueueAsyncClient(client, queueName); + + return queueAsyncClient.create(metadata) + .map(response -> new SimpleResponse<>(response, queueAsyncClient)); + } + + /** + * Deletes a queue in the storage account + * + *

Code Samples

+ * + *

Delete the queue "test"

+ * + * {@codesnippet com.azure.storage.queue.queueServiceAsyncClient.deleteQueue#string} + * + * @param queueName Name of the queue + * @return A response that only contains headers and response status code + * @throws StorageErrorException If the queue doesn't exist + */ + public Mono deleteQueue(String queueName) { + return new QueueAsyncClient(client, queueName).delete(); + } + + /** + * Lists all queues in the storage account without their metadata. + * + *

Code Samples

+ * + *

List all queues in the account

+ * + * {@codesnippet com.azure.storage.queue.queueServiceAsyncClient.listQueues} + * + * @return {@link QueueItem Queues} in the storage account + */ + public Flux listQueues() { + return listQueues(null, null); + } + + /** + * Lists the queues in the storage account that pass the filter. + * + * Pass true to {@link QueuesSegmentOptions#includeMetadata(boolean) includeMetadata} to have metadata returned for + * the queues. + * + *

Code Samples

+ * + *

List all queues that begin with "azure"

+ * + * {@codesnippet com.azure.storage.queue.queueServiceClient.listQueues#queueSergmentOptions} + * + * @param options Options for listing queues + * @return {@link QueueItem Queues} in the storage account that satisfy the filter requirements + */ + public Flux listQueues(QueuesSegmentOptions options) { + return listQueues(null, options); + } + + /** + * Lists the queues in the storage account that pass the filter starting at the specified marker. + * + * Pass true to {@link QueuesSegmentOptions#includeMetadata(boolean) includeMetadata} to have metadata returned for + * the queues. + * + * @param marker Starting point to list the queues + * @param options Options for listing queues + * @return {@link QueueItem Queues} in the storage account that satisfy the filter requirements + */ + Flux listQueues(String marker, QueuesSegmentOptions options) { + String prefix = null; + Integer maxResults = null; + final List include = new ArrayList<>(); + + if (options != null) { + prefix = options.prefix(); + maxResults = options.maxResults(); + if (options.includeMetadata()) { + include.add(ListQueuesIncludeType.fromString(ListQueuesIncludeType.METADATA.toString())); + } + } + + Mono result = client.services() + .listQueuesSegmentWithRestResponseAsync(prefix, marker, maxResults, include, null, null, Context.NONE); + + return result.flatMapMany(response -> extractAndFetchQueues(response, include, Context.NONE)); + } + + /* + * Helper function used to auto-enumerate through paged responses + */ + private Flux listQueues(ServicesListQueuesSegmentResponse response, List include, Context context) { + ListQueuesSegmentResponse value = response.value(); + Mono result = client.services() + .listQueuesSegmentWithRestResponseAsync(value.prefix(), value.marker(), value.maxResults(), include, null, null, context); + + return result.flatMapMany(r -> extractAndFetchQueues(r, include, context)); + } + + /* + * Helper function used to auto-enumerate though paged responses + */ + private Flux extractAndFetchQueues(ServicesListQueuesSegmentResponse response, List include, Context context) { + String nextPageLink = response.value().nextMarker(); + if (nextPageLink == null) { + return Flux.fromIterable(response.value().queueItems()); + } + + return Flux.fromIterable(response.value().queueItems()).concatWith(listQueues(response, include, context)); + } + + /** + * Retrieves the properties of the storage account's Queue service. The properties range from storage analytics and + * metric to CORS (Cross-Origin Resource Sharing). + * + *

Code Samples

+ * + *

Retrieve Queue service properties

+ * + * {@codesnippet com.azure.storage.queue.queueServiceAsyncClient.getProperties} + * + * @return Storage account Queue service properties + */ + public Mono> getProperties() { + return client.services().getPropertiesWithRestResponseAsync(Context.NONE) + .map(response -> new SimpleResponse<>(response, response.value())); + } + + /** + * Sets the properties for the storage account's Queue 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 StorageServiceProperties#cors() CORS}. + * To disable all CORS in the Queue service pass an empty list for {@link StorageServiceProperties#cors() CORS}. + * + *

Code Sample

+ * + *

Clear CORS in the Queue service

+ * + * {@codesnippet com.azure.storage.queue.queueServiceAsyncClient.setProperties#storageServiceProperties} + * + *

Enable Minute and Hour Metrics

+ * + * {@codesnippet com.azure.storage.queue.queueServiceAsyncClient.setPropertiesEnableMetrics#storageServiceProperties} + * + * @param properties Storage account Queue 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(StorageServiceProperties properties) { + return client.services().setPropertiesWithRestResponseAsync(properties, Context.NONE) + .map(VoidResponse::new); + } + + /** + * Retrieves the geo replication information about the Queue service. + * + *

Code Samples

+ * + *

Retrieve the geo replication information

+ * + * {@codesnippet com.azure.storage.queue.queueServiceAsyncClient.getStatistics} + * + * @return The geo replication information about the Queue service + */ + public Mono> getStatistics() { + return client.services().getStatisticsWithRestResponseAsync(Context.NONE) + .map(response -> new SimpleResponse<>(response, response.value())); + } +} diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/QueueServiceClient.java b/storage/client/queue/src/main/java/com/azure/storage/queue/QueueServiceClient.java new file mode 100644 index 0000000000000..a002e5b12f872 --- /dev/null +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/QueueServiceClient.java @@ -0,0 +1,234 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.storage.queue; + +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.queue.models.CorsRule; +import com.azure.storage.queue.models.QueueItem; +import com.azure.storage.queue.models.QueuesSegmentOptions; +import com.azure.storage.queue.models.StorageErrorException; +import com.azure.storage.queue.models.StorageServiceProperties; +import com.azure.storage.queue.models.StorageServiceStats; +import java.net.URL; +import java.util.Map; + +/** + * This class provides a client that contains all the operations for interacting with a queue account in Azure Storage. + * Operations allowed by the client are creating, listing, and deleting queues, retrieving and updating properties of the account, + * and retrieving statistics of the account. + * + *

Instantiating an Synchronous Queue Service Client

+ * + * {@codesnippet com.azure.storage.queue.queueServiceClient.instantiation} + * + *

View {@link QueueServiceClientBuilder this} for additional ways to construct the client.

+ * + * @see QueueServiceClientBuilder + * @see QueueServiceAsyncClient + * @see SharedKeyCredential + * @see SASTokenCredential + */ +public final class QueueServiceClient { + private final QueueServiceAsyncClient client; + + /** + * Creates a QueueServiceClient that wraps a QueueServiceAsyncClient and blocks requests. + * + * @param client QueueServiceAsyncClient that is used to send requests + */ + QueueServiceClient(QueueServiceAsyncClient client) { + this.client = client; + } + + /** + * @return the URL of the storage queue + */ + public URL getQueueServiceUrl() { + return client.getQueueServiceUrl(); + } + + /** + * Constructs a QueueClient that interacts with the specified queue. + * + * This will not create the queue in the storage account if it doesn't exist. + * + * @param queueName Name of the queue + * @return QueueClient that interacts with the specified queue + */ + public QueueClient getQueueClient(String queueName) { + return new QueueClient(client.getQueueAsyncClient(queueName)); + } + + /** + * Creates a queue in the storage account with the specified name and returns a QueueClient to interact with it. + * + *

Code Samples

+ * + *

Create the queue "test"

+ * + * {@codesnippet com.azure.storage.queue.queueServiceClient.createQueue#string} + * + * @param queueName Name of the queue + * @return A response containing the QueueClient and the status of creating the queue + * @throws StorageErrorException If a queue with the same name and different metadata already exists + */ + public Response createQueue(String queueName) { + return createQueue(queueName, null); + } + + /** + * Creates a queue in the storage account with the specified name and metadata and returns a QueueClient to + * interact with it. + * + *

Code Samples

+ * + *

Create the queue "test" with metadata "queue:metadata"

+ * + * {@codesnippet com.azure.storage.queue.queueServiceClient.createQueue#string-map} + * + * @param queueName Name of the queue + * @param metadata Metadata to associate with the queue + * @return A response containing the QueueClient and the status of creating the queue + * @throws StorageErrorException If a queue with the same name and different metadata already exists + */ + public Response createQueue(String queueName, Map metadata) { + Response response = client.createQueue(queueName, metadata).block(); + + return new SimpleResponse<>(response, new QueueClient(response.value())); + } + + /** + * Deletes a queue in the storage account + * + *

Code Samples

+ * + *

Delete the queue "test"

+ * + * {@codesnippet com.azure.storage.queue.queueServiceClient.deleteQueue#string} + * + * @param queueName Name of the queue + * @return A response containing the status of deleting the queue + * @throws StorageErrorException If the queue doesn't exist + */ + public VoidResponse deleteQueue(String queueName) { + return client.deleteQueue(queueName).block(); + } + + /** + * Lists all queues in the storage account without their metadata. + * + *

Code Samples

+ * + *

List all queues in the account

+ * + * {@codesnippet com.azure.storage.queue.queueServiceClient.listQueues} + * + * @return {@link QueueItem Queues} in the storage account + */ + public Iterable listQueues() { + return listQueues(null, null); + } + + /** + * Lists the queues in the storage account that pass the filter. + * + * Pass true to {@link QueuesSegmentOptions#includeMetadata(boolean) includeMetadata} to have metadata returned for + * the queues. + * + *

Code Samples

+ * + *

List all queues that begin with "azure"

+ * + * {@codesnippet com.azure.storage.queue.queueServiceClient.listQueues#queueSergmentOptions} + * + * @param options Options for listing queues + * @return {@link QueueItem Queues} in the storage account that satisfy the filter requirements + */ + public Iterable listQueues(QueuesSegmentOptions options) { + return listQueues(null, options); + } + + /** + * Lists the queues in the storage account that pass the filter starting at the specified marker. + * + * Pass true to {@link QueuesSegmentOptions#includeMetadata(boolean) includeMetadata} to have metadata returned for + * the queues. + * + * @param marker Starting point to list the queues + * @param options Options for listing queues + * @return {@link QueueItem Queues} in the storage account that satisfy the filter requirements + */ + Iterable listQueues(String marker, QueuesSegmentOptions options) { + return client.listQueues(marker, options).toIterable(); + } + + /** + * Retrieves the properties of the storage account's Queue service. The properties range from storage analytics and + * metric to CORS (Cross-Origin Resource Sharing). + * + *

Code Samples

+ * + *

Retrieve Queue service properties

+ * + * {@codesnippet com.azure.storage.queue.queueServiceClient.getProperties} + * + * @return Storage account Queue service properties + */ + public Response getProperties() { + return client.getProperties().block(); + } + + /** + * Sets the properties for the storage account's Queue 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 StorageServiceProperties#cors() CORS}. + * To disable all CORS in the Queue service pass an empty list for {@link StorageServiceProperties#cors() CORS}. + * + *

Code Sample

+ * + *

Clear CORS in the Queue service

+ * + * {@codesnippet com.azure.storage.queue.queueServiceClient.setProperties#storageServiceProperties} + * + *

Enable Minute and Hour Metrics

+ * + * {@codesnippet com.azure.storage.queue.queueServiceClient.setPropertiesEnableMetrics#storageServiceProperties} + * + * @param properties Storage account Queue 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(StorageServiceProperties properties) { + return client.setProperties(properties).block(); + } + + /** + * Retrieves the geo replication information about the Queue service. + * + *

Code Samples

+ * + *

Retrieve the geo replication information

+ * + * {@codesnippet com.azure.storage.queue.queueServiceClient.getStatistics} + * + * @return The geo replication information about the Queue service + */ + public Response getStatistics() { + return client.getStatistics().block(); + } +} diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/QueueServiceClientBuilder.java b/storage/client/queue/src/main/java/com/azure/storage/queue/QueueServiceClientBuilder.java new file mode 100644 index 0000000000000..63b191256f5dd --- /dev/null +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/QueueServiceClientBuilder.java @@ -0,0 +1,301 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.storage.queue; + +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.core.util.logging.ClientLogger; +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.List; +import java.util.Objects; + +/** + * This class provides a fluent builder API to help aid the configuration and instantiation of the {@link QueueServiceClient queueServiceClients} + * and {@link QueueServiceAsyncClient queueServiceAsyncClients}, calling {@link QueueServiceClientBuilder#buildClient() buildClient} + * constructs an instance of QueueServiceClient and calling {@link QueueServiceClientBuilder#buildAsyncClient() buildAsyncClient} + * constructs an instance of QueueServiceAsyncClient. + * + *

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

+ * + *

Instantiating a synchronous Queue Service Client with SAS token

+ * {@codesnippet com.azure.storage.queue.queueServiceClient.instantiation.sastoken} + * + *

Instantiating an Asynchronous Queue Service Client with SAS token

+ * {@codesnippet com.azure.storage.queue.queueServiceAsyncClient.instantiation.sastoken} + * + *

If the {@code endpoint} doesn't contain {@code SASTokenCredential} they may be set using + * {@link QueueClientBuilder#credential(SASTokenCredential) credential}.

+ * + *

Instantiating a synchronous Queue Service Client with SAS token

+ * {@codesnippet com.azure.storage.queue.queueServiceAsyncClient.instantiation.credential} + * + *

Instantiating an Asynchronous Queue Service Client with SAS token

+ * {@codesnippet com.azure.storage.queue.queueServiceAsyncClient.instantiation.credential} + * + *

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

+ * + *

Another way to authenticate the client is using a {@link SharedKeyCredential}. To create a SharedKeyCredential + * a connection string from the Storage Queue service must be used. Set the SharedKeyCredential with + * {@link QueueServiceClientBuilder#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 Queue Service Client with connection string.

+ * {@codesnippet com.azure.storage.queue.queueServiceClient.instantiation.connectionstring} + * + *

Instantiating an Asynchronous Queue Service Client with connection string.

+ * {@codesnippet com.azure.storage.queue.queueServiceAsyncClient.instantiation.connectionstring} + * + * @see QueueServiceClient + * @see QueueServiceAsyncClient + * @see SASTokenCredential + * @see SharedKeyCredential + */ +public final class QueueServiceClientBuilder { + private static final ClientLogger LOGGER = new ClientLogger(QueueServiceClientBuilder.class); + 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 QueueServiceClient QueueServiceClients} + * and {@link QueueServiceAsyncClient QueueServiceAsyncClients}. + */ + public QueueServiceClientBuilder() { + retryPolicy = new RetryPolicy(); + logLevel = HttpLogDetailLevel.NONE; + policies = new ArrayList<>(); + configuration = ConfigurationManager.getConfiguration(); + } + + /** + * Creates a {@link QueueServiceAsyncClient} based on options set in the builder. Every time {@code buildAsyncClient()} is + * called a new instance of {@link QueueServiceAsyncClient} is created. + * + *

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

+ * + * @return A QueueServiceAsyncClient with the options set from the builder. + * @throws NullPointerException If {@code endpoint} or {@code queueName} have not been set. + * @throws IllegalArgumentException If neither a {@link SharedKeyCredential} or {@link SASTokenCredential} has been set. + */ + public QueueServiceAsyncClient buildAsyncClient() { + Objects.requireNonNull(endpoint); + + if (sasTokenCredential == null && sharedKeyCredential == null) { + LOGGER.asError().log("Credentials are required for authorization"); + throw new IllegalArgumentException("Credentials are required for authorization"); + } + + if (pipeline != null) { + return new QueueServiceAsyncClient(endpoint, pipeline); + } + // Closest to API goes first, closest to wire goes last. + final List policies = new ArrayList<>(); + + policies.add(new UserAgentPolicy(QueueConfiguration.NAME, QueueConfiguration.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 QueueServiceAsyncClient(endpoint, pipeline); + } + + /** + * Creates a {@link QueueServiceClient} based on options set in the builder. Every time {@code buildClient()} is + * called a new instance of {@link QueueServiceClient} is created. + * + *

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

+ * + * @return A QueueServiceClient with the options set from the builder. + * @throws NullPointerException If {@code endpoint} or {@code queueName} have not been set. + * @throws IllegalStateException If neither a {@link SharedKeyCredential} or {@link SASTokenCredential} has been set. + */ + public QueueServiceClient buildClient() { + return new QueueServiceClient(buildAsyncClient()); + } + + + /** + * Sets the endpoint for the Azure Storage Queue 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 Queue instance to send service requests to and receive responses from. + * @return the updated QueueServiceClientBuilder object + * @throws IllegalArgumentException If {@code endpoint} isn't a proper URL + */ + public QueueServiceClientBuilder endpoint(String endpoint) { + Objects.requireNonNull(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 + SASTokenCredential credential = SASTokenCredential.fromQuery(fullURL.getQuery()); + if (credential != null) { + this.sasTokenCredential = credential; + } + } catch (MalformedURLException ex) { + LOGGER.asError().log("The Azure Storage Queue endpoint url is malformed."); + throw new IllegalArgumentException("The Azure Storage Queue 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 QueueServiceClientBuilder object + * @throws NullPointerException If {@code credential} is {@code null}. + */ + public QueueServiceClientBuilder credential(SASTokenCredential credential) { + this.sasTokenCredential = Objects.requireNonNull(credential); + return this; + } + + /** + * Sets the {@link SharedKeyCredential} used to authenticate requests sent to the Queue service. + * + * @param credential Shared key credential can retrieve from the Storage account that authorizes requests + * @return the updated QueueServiceClientBuilder object + * @throws NullPointerException If {@code credential} is {@code null}. + */ + public QueueServiceClientBuilder credential(SharedKeyCredential credential) { + this.sharedKeyCredential = Objects.requireNonNull(credential); + return this; + } + + + /** + * Creates a {@link SharedKeyCredential} from the {@code connectionString} used to authenticate requests sent to the + * Queue service. + * + * @param connectionString Connection string from the Access Keys section in the Storage account + * @return the updated QueueServiceClientBuilder object + * @throws NullPointerException If {@code connectionString} is {@code null}. + */ + public QueueServiceClientBuilder connectionString(String connectionString) { + Objects.requireNonNull(connectionString); + this.sharedKeyCredential = SharedKeyCredential.fromConnectionString(connectionString); + 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 QueueServiceClientBuilder object. + * @throws NullPointerException If {@code httpClient} is {@code null}. + */ + public QueueServiceClientBuilder 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 QueueServiceClientBuilder object. + * @throws NullPointerException If {@code pipelinePolicy} is {@code null}. + */ + public QueueServiceClientBuilder 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 QueueServiceClientBuilder object. + */ + public QueueServiceClientBuilder 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 QueueServiceClientBuilder#endpoint(String) endpoint} + * when building clients. + * + * @param pipeline The HTTP pipeline to use for sending service requests and receiving responses. + * @return The updated QueueServiceClientBuilder object. + * @throws NullPointerException If {@code pipeline} is {@code null}. + */ + public QueueServiceClientBuilder pipeline(HttpPipeline pipeline) { + Objects.requireNonNull(pipeline); + this.pipeline = 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 QueueServiceClientBuilder object. + */ + public QueueServiceClientBuilder configuration(Configuration configuration) { + this.configuration = configuration; + return this; + } +} diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/README.md b/storage/client/queue/src/main/java/com/azure/storage/queue/README.md new file mode 100644 index 0000000000000..86ffe940daf0c --- /dev/null +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/README.md @@ -0,0 +1,377 @@ +# Azure Storage Queue client library for Java +Azure Queue storage is a service for storing large numbers of messages that can be accessed from anywhere in the world via authenticated calls using HTTP or HTTPS. +A single queue message can be up to 64 KB in size, and a queue can contain millions of messages, up to the total capacity limit of a storage account. + +[Source code][source_code] | [Package (Maven)][package] | [API reference documentation][api_documentation] | [Product documentation][storage_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 + 12.0.0 + +``` + +### 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 (Blob, Queue, Message, 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 queue generate-sas + --name {queue 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 queue 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 (after setup) +``` + +- **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 +Queues are addressable using the following URL format: +https://.queue.core.windows.net/ +The following URL addresses a queue in the diagram: +https://myaccount.queue.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: +```$xslt +https://myaccount.queue.core.windows.net +``` +For a queue, the base URI includes the name of the account and the name of the queue: +```$xslt +https://myaccount.queue.core.windows.net/myqueue +``` + +### Handling Exceptions + +```java +TODO +``` + +### Queue Names +Every queue within an account must have a unique name. The queue name must be a valid DNS name, and cannot be changed once created. Queue names must confirm to the following rules: +1. A queue name must start with a letter or number, and can only contain letters, numbers, and the dash (-) character. +1. The first and last letters in the queue name must be alphanumeric. The dash (-) character cannot be the first or last character. Consecutive dash characters are not permitted in the queue name. +1. All letters in a queue name must be lowercase. +1. A queue name must be from 3 through 63 characters long. + +### Queue Services +The queue service do operations on the queues in the storage account and manage the queue properties. + +### Queue Service Client + +The client performs the interactions with the Queue service, create or delete a queue, getting and setting Queue properties, list queues in account, and get queue statistics. An asynchronous, `QueueServiceAsyncClient`, and synchronous, `QueueClient`, client exists in the SDK allowing for selection of a client based on an application's use case. +Once you have the value of the SASToken you can create the queue service client with `${accountName}`, `${sasToken}`. +```Java +String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", accountName, sasToken) +QueueServiceClient queueServiceClient = QueueServiceClient.builder().endpoint(queueURL).build(); + +QueueClient newQueueServiceClient = queueServiceClient.createQueue("myqueue"); +``` + +or + +```Java +String queueServiceAsyncURL = String.format("https://%s.queue.core.windows.net/%s", accountName, sasToken) +QueueServiceAsyncClient queueServiceAsyncClient = QueueServiceAsyncClient.builder().endpoint(queueServiceAsyncURL).build(); +queueServiceAsyncClient.createQueue("newAsyncQueue").subscribe( + result -> { + // do something when new queue created + }, + error -> { + // do something if something wrong happened + }, + () -> { + // completed, do something + }); +``` + +### Queue +Azure Queue storage is a service for storing large numbers of messages that can be accessed from anywhere in the world via authenticated calls using HTTP or HTTPS. +A single queue message can be up to 64 KB in size, and a queue can contain millions of messages, up to the total capacity limit of a storage account. + +### QueueClient +Once you have the value of the SASToken you can create the queue service client with `${accountName}`, `${queueName}`, `${sasToken}`. +```Java +String queueURL = String.format("https://%s.queue.core.windows.net/%s%s", accountName, queueName, sasToken); +QueueClient queueClient = QueueClient.builder().endpoint(queueURL).build(); +// metadata is map of key-value pair, timeout is client side timeout +QueueClient newQueueClient = queueClient.create(metadata, timeout); +``` + +or + +```Java +String queueAsyncURL = String.format("https://%s.queue.core.windows.net/%s%s", accountName, queueAsyncName, sasToken) +QueueAsyncClient queueAsyncClient = QueueAsyncClient.builder().endpoint(queueAsyncURL).build(); +queueAsyncClient.create(metadata, timeout).subscribe( + result -> { + // do something when new queue created + }, + error -> { + // do something if something wrong happened + }, + () -> { + // completed, do something + }); +``` + +## Examples + +The following sections provide several code snippets covering some of the most common Configuration Service tasks, including: +- [Create a Queue](#Create-a-queue) +- [Delete a queue](#Delete-a-queue) +- [List the queues in account](#List-queues-in-account) +- [Get propertiesin Queue account](#Get-properties-in-queue-account) +- [Set propertiesin Queue account](#Set-properties-in-queue-account) +- [Get statistcs of queue](#Get-queue-service-statistics) +- [Enqueue message into a queue](#Enqueue-message-into-a-queue) +- [Update message into a queue](#Update-message-into-a-queue) +- [Peek messages into a queue](#Peek-messages-into-a-queue) +- [Dequeue messages from a queue](#Dequeue-messages-from-a-queue) +- [Delete message from a queue](#Delete-message-from-a-queue) +- [Get a Queue properties](#Get-a-queue-properties) +- [Set/Update a Queue metadata](#Set-a-queue-metadata) +### Create a queue + +Create a queue in the Storage Account. Throws StorageErrorException If the queue fails to be created. + +```Java +String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", accountName, sasToken) +QueueServiceClient queueServiceClient = QueueServiceClient.builder().endpoint(queueURL).build(); + +QueueClient newQueueServiceClient = queueServiceClient.createQueue("myqueue"); +``` +### Delete a queue + +Delete a queue in the Storage Account. Throws StorageErrorException If the queue fails to be deleted. +```Java +String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", accountName, sasToken) +QueueServiceClient queueServiceClient = QueueServiceClient.builder().endpoint(queueURL).build(); + +QueueClient newQueueServiceClient = queueServiceClient.deleteQueue("myqueue"); +``` + +### List queues in account + +List all the queues in account. +```Java +String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", accountName, sasToken) +QueueServiceClient queueServiceClient = QueueServiceClient.builder().endpoint(queueURL).build(); +// @param marker: Starting point to list the queues +// @param options: Filter for queue selection +queueServiceClient.listQueuesSegment(marker, options).forEach{ + queueItem -> {//do something} +}; +``` + +### Get properties in queue account + +Get queue properties in account, including properties for Storage Analytics and CORS (Cross-Origin Resource Sharing) rules. +```Java +String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", accountName, sasToken) +QueueServiceClient queueServiceClient = QueueServiceClient.builder().endpoint(queueURL).build(); + +Response properties = queueServiceClient.getProperties(); +``` + +### Set properties in queue account + +Set queue properties in account, including properties for Storage Analytics and CORS (Cross-Origin Resource Sharing) rules. +```Java +String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", accountName, sasToken) +QueueServiceClient queueServiceClient = QueueServiceClient.builder().endpoint(queueURL).build(); + +StorageServiceProperties properties = new StorageServiceProperties() { + // logging: some logging; + // HourMetrics: some metrics + // MinuteMetrics: some metrics + // Cors: some cors +} + +queueServiceClient.setProperties(properties); +``` + +### Get queue service statistics +he `Get Queue Service Stats` operation retrieves statistics related to replication for the Queue service. +It is only available on the secondary location endpoint when read-access geo-redundant replication is enabled for the storage account. +```Java +String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", accountName, sasToken) +QueueServiceClient queueServiceClient = QueueServiceClient.builder().endpoint(queueURL).build(); + +Response queueStats = queueServiceClient.getStatistics(); +``` + +### Enqueue message into a queue +The operation adds a new message to the back of the message queue. A visibility timeout can also be specified to make the message invisible until the visibility timeout expires. +A message must be in a format that can be included in an XML request with UTF-8 encoding. The encoded message can be up to 64 KB in size for versions 2011-08-18 and newer, or 8 KB in size for previous versions. +```Java +String queueURL = String.format("https://%s.queue.core.windows.net/%s%s", accountName, queueName, sasToken); +QueueClient queueClient = QueueClient.builder().endpoint(queueURL).build(); + +queueClient.enqueueMessage("myMessage"); +``` + +### Update messaged from a queue +The operation updates a message in the message queue. +```Java +String queueURL = String.format("https://%s.queue.core.windows.net/%s%s", accountName, queueName, sasToken); +QueueClient queueClient = QueueClient.builder().endpoint(queueURL).build(); +// @param messageId Id of the message +// @param popReceipt Unique identifier that must match the message for it to be updated +// @param visibilityTimeout How long the message will be invisible in the queue in seconds +queueClient.updateMessage(messageId, "new message", popReceipt, visibilityTimeout); +``` + +### Peek messages from a queue +The operation retrieves one or more messages from the front of the queue. +```Java +String queueURL = String.format("https://%s.queue.core.windows.net/%s%s", accountName, queueName, sasToken); +QueueClient queueClient = QueueClient.builder().endpoint(queueURL).build(); + +queueClient.peekMessages().forEach(message-> {print message.messageText();}); +``` + + +### Dequeue messages from a queue +The operation retrieves one or more messages from the front of the queue. +```Java +String queueURL = String.format("https://%s.queue.core.windows.net/%s%s", accountName, queueName, sasToken); +QueueClient queueClient = QueueClient.builder().endpoint(queueURL).build(); + +queueClient.dequeueMessage("myMessage").forEach(message-> {print message.messageText();}); +``` + + +### Delete message from a queue +The operation retrieves one or more messages from the front of the queue. +```Java +String queueURL = String.format("https://%s.queue.core.windows.net/%s%s", accountName, queueName, sasToken); +QueueClient queueClient = QueueClient.builder().endpoint(queueURL).build(); + +queueClient.deleteMessage(messageId, popReceipt); +``` + +### Get a queue properties +The operation retrieves user-defined metadata and queue properties on the specified queue. Metadata is associated with the queue as name-values pairs. +```Java +String queueURL = String.format("https://%s.queue.core.windows.net/%s%s", accountName, queueName, sasToken); +QueueClient queueClient = QueueClient.builder().endpoint(queueURL).build(); + +Response properties = queueClient.getProperties(); +``` + +### Set a queue metadata +The operation sets user-defined metadata on the specified queue. Metadata is associated with the queue as name-value pairs. +```Java +String queueURL = String.format("https://%s.queue.core.windows.net/%s%s", accountName, queueName, sasToken); +QueueClient queueClient = QueueClient.builder().endpoint(queueURL).build(); + +Map metadata = new HashMap<>() {{ + put("key1", "val1"); + put("key2", "val2"); +}}; +queueClient.setMetadata(metadata); +``` + + +## Troubleshooting + +## General + +When you interact with queue using this Java client library, errors returned by the service correspond to the same HTTP status codes returned for [REST API][storage_rest] requests. For example, if you try to retrieve a queue that doesn't exist in your Storage Account, a `404` error is returned, indicating `Not Found`. + +## Next steps + +### More Samples +- QueueServiceSample +- MessageSample +- QueueExceptionSample +- AsyncSample + +[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/queue-service-rest-api +[storage_docs]: https://docs.microsoft.com/en-us/azure/storage/queues/storage-queues-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 +[storage_rest]: https://docs.microsoft.com/en-us/rest/api/storageservices/queue-service-error-codes diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/AzureQueueStorageBuilder.java b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/AzureQueueStorageBuilder.java index 4f678dfe10832..f3582e10e1a44 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/AzureQueueStorageBuilder.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/AzureQueueStorageBuilder.java @@ -75,9 +75,7 @@ public AzureQueueStorageImpl build() { if (this.url != null) { client.url(this.url); } - if (this.version != null) { - client.version(this.version); - } + client.version(this.version); return client; } } diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessageIdsImpl.java b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessageIdsImpl.java index 8a705fe7e4af7..f5e6c952f5de1 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessageIdsImpl.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessageIdsImpl.java @@ -10,6 +10,7 @@ import com.azure.core.annotations.HeaderParam; import com.azure.core.annotations.Host; import com.azure.core.annotations.HostParam; +import com.azure.core.annotations.PathParam; import com.azure.core.annotations.PUT; import com.azure.core.annotations.QueryParam; import com.azure.core.annotations.Service; @@ -57,12 +58,12 @@ private interface MessageIdsService { @PUT("{queueName}/messages/{messageid}") @ExpectedResponses({204}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono update(@HostParam("url") String url, @BodyParam("application/xml; charset=utf-8") QueueMessage queueMessage, @QueryParam("popreceipt") String popReceipt, @QueryParam("visibilitytimeout") int visibilitytimeout, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context); + Mono update(@HostParam("url") String url, @PathParam("queueName") String queueName, @PathParam("messageid") String messageId, @BodyParam("application/xml; charset=utf-8") QueueMessage queueMessage, @QueryParam("popreceipt") String popReceipt, @QueryParam("visibilitytimeout") int visibilitytimeout, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context); @DELETE("{queueName}/messages/{messageid}") @ExpectedResponses({204}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono delete(@HostParam("url") String url, @QueryParam("popreceipt") String popReceipt, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context); + Mono delete(@HostParam("url") String url, @PathParam("queueName") String queueName, @PathParam("messageid") String messageId, @QueryParam("popreceipt") String popReceipt, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context); } /** @@ -75,10 +76,10 @@ private interface MessageIdsService { * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono updateWithRestResponseAsync(QueueMessage queueMessage, String popReceipt, int visibilitytimeout, Context context) { + public Mono updateWithRestResponseAsync(String queueName, String messageId, QueueMessage queueMessage, String popReceipt, int visibilitytimeout, Context context) { final Integer timeout = null; final String requestId = null; - return service.update(this.client.url(), queueMessage, popReceipt, visibilitytimeout, timeout, this.client.version(), requestId, context); + return service.update(this.client.url(), queueName, messageId, queueMessage, popReceipt, visibilitytimeout, timeout, this.client.version(), requestId, context); } /** @@ -93,8 +94,8 @@ public Mono updateWithRestResponseAsync(QueueMessage q * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono updateWithRestResponseAsync(QueueMessage queueMessage, String popReceipt, int visibilitytimeout, Integer timeout, String requestId, Context context) { - return service.update(this.client.url(), queueMessage, popReceipt, visibilitytimeout, timeout, this.client.version(), requestId, context); + public Mono updateWithRestResponseAsync(String queueName, String messageId, QueueMessage queueMessage, String popReceipt, int visibilitytimeout, Integer timeout, String requestId, Context context) { + return service.update(this.client.url(), queueName, messageId, queueMessage, popReceipt, visibilitytimeout, timeout, this.client.version(), requestId, context); } /** @@ -105,10 +106,10 @@ public Mono updateWithRestResponseAsync(QueueMessage q * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono deleteWithRestResponseAsync(String popReceipt, Context context) { + public Mono deleteWithRestResponseAsync(String queueName, String messageId, String popReceipt, Context context) { final Integer timeout = null; final String requestId = null; - return service.delete(this.client.url(), popReceipt, timeout, this.client.version(), requestId, context); + return service.delete(this.client.url(), queueName, messageId, popReceipt, timeout, this.client.version(), requestId, context); } /** @@ -121,7 +122,7 @@ public Mono deleteWithRestResponseAsync(String popRece * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono deleteWithRestResponseAsync(String popReceipt, Integer timeout, String requestId, Context context) { - return service.delete(this.client.url(), popReceipt, timeout, this.client.version(), requestId, context); + public Mono deleteWithRestResponseAsync(String queueName, String messageId, String popReceipt, Integer timeout, String requestId, Context context) { + return service.delete(this.client.url(), queueName, messageId, popReceipt, timeout, this.client.version(), requestId, context); } } diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessagesImpl.java b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessagesImpl.java index ee59aae16b63f..84f680cad1dba 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessagesImpl.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessagesImpl.java @@ -11,6 +11,7 @@ import com.azure.core.annotations.HeaderParam; import com.azure.core.annotations.Host; import com.azure.core.annotations.HostParam; +import com.azure.core.annotations.PathParam; import com.azure.core.annotations.POST; import com.azure.core.annotations.QueryParam; import com.azure.core.annotations.Service; @@ -60,22 +61,22 @@ private interface MessagesService { @GET("{queueName}/messages") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono dequeue(@HostParam("url") String url, @QueryParam("numofmessages") Integer numberOfMessages, @QueryParam("visibilitytimeout") Integer visibilitytimeout, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context); + Mono dequeue(@HostParam("url") String url, @PathParam("queueName") String queueName, @QueryParam("numofmessages") Integer numberOfMessages, @QueryParam("visibilitytimeout") Integer visibilitytimeout, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context); @DELETE("{queueName}/messages") @ExpectedResponses({204}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono clear(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context); + Mono clear(@HostParam("url") String url, @PathParam("queueName") String queueName, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context); @POST("{queueName}/messages") @ExpectedResponses({201}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono enqueue(@HostParam("url") String url, @BodyParam("application/xml; charset=utf-8") QueueMessage queueMessage, @QueryParam("visibilitytimeout") Integer visibilitytimeout, @QueryParam("messagettl") Integer messageTimeToLive, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context); + Mono enqueue(@HostParam("url") String url, @PathParam("queueName") String queueName, @BodyParam("application/xml; charset=utf-8") QueueMessage queueMessage, @QueryParam("visibilitytimeout") Integer visibilitytimeout, @QueryParam("messagettl") Integer messageTimeToLive, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context); @GET("{queueName}/messages") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono peek(@HostParam("url") String url, @QueryParam("numofmessages") Integer numberOfMessages, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("peekonly") String peekonly, Context context); + Mono peek(@HostParam("url") String url, @PathParam("queueName") String queueName, @QueryParam("numofmessages") Integer numberOfMessages, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("peekonly") String peekonly, Context context); } /** @@ -85,12 +86,12 @@ private interface MessagesService { * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono dequeueWithRestResponseAsync(Context context) { + public Mono dequeueWithRestResponseAsync(String queueName, Context context) { final Integer numberOfMessages = null; final Integer visibilitytimeout = null; final Integer timeout = null; final String requestId = null; - return service.dequeue(this.client.url(), numberOfMessages, visibilitytimeout, timeout, this.client.version(), requestId, context); + return service.dequeue(this.client.url(), queueName, numberOfMessages, visibilitytimeout, timeout, this.client.version(), requestId, context); } /** @@ -104,8 +105,8 @@ public Mono dequeueWithRestResponseAsync(Context contex * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono dequeueWithRestResponseAsync(Integer numberOfMessages, Integer visibilitytimeout, Integer timeout, String requestId, Context context) { - return service.dequeue(this.client.url(), numberOfMessages, visibilitytimeout, timeout, this.client.version(), requestId, context); + public Mono dequeueWithRestResponseAsync(String queueName, Integer numberOfMessages, Integer visibilitytimeout, Integer timeout, String requestId, Context context) { + return service.dequeue(this.client.url(), queueName, numberOfMessages, visibilitytimeout, timeout, this.client.version(), requestId, context); } /** @@ -115,10 +116,10 @@ public Mono dequeueWithRestResponseAsync(Integer number * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono clearWithRestResponseAsync(Context context) { + public Mono clearWithRestResponseAsync(String queueName, Context context) { final Integer timeout = null; final String requestId = null; - return service.clear(this.client.url(), timeout, this.client.version(), requestId, context); + return service.clear(this.client.url(), queueName, timeout, this.client.version(), requestId, context); } /** @@ -130,8 +131,8 @@ public Mono clearWithRestResponseAsync(Context context) { * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono clearWithRestResponseAsync(Integer timeout, String requestId, Context context) { - return service.clear(this.client.url(), timeout, this.client.version(), requestId, context); + public Mono clearWithRestResponseAsync(String queueName, Integer timeout, String requestId, Context context) { + return service.clear(this.client.url(), queueName, timeout, this.client.version(), requestId, context); } /** @@ -142,12 +143,12 @@ public Mono clearWithRestResponseAsync(Integer timeout, S * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono enqueueWithRestResponseAsync(QueueMessage queueMessage, Context context) { + public Mono enqueueWithRestResponseAsync(String queueName, QueueMessage queueMessage, Context context) { final Integer visibilitytimeout = null; final Integer messageTimeToLive = null; final Integer timeout = null; final String requestId = null; - return service.enqueue(this.client.url(), queueMessage, visibilitytimeout, messageTimeToLive, timeout, this.client.version(), requestId, context); + return service.enqueue(this.client.url(), queueName, queueMessage, visibilitytimeout, messageTimeToLive, timeout, this.client.version(), requestId, context); } /** @@ -162,8 +163,8 @@ public Mono enqueueWithRestResponseAsync(QueueMessage q * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono enqueueWithRestResponseAsync(QueueMessage queueMessage, Integer visibilitytimeout, Integer messageTimeToLive, Integer timeout, String requestId, Context context) { - return service.enqueue(this.client.url(), queueMessage, visibilitytimeout, messageTimeToLive, timeout, this.client.version(), requestId, context); + public Mono enqueueWithRestResponseAsync(String queueName, QueueMessage queueMessage, Integer visibilitytimeout, Integer messageTimeToLive, Integer timeout, String requestId, Context context) { + return service.enqueue(this.client.url(), queueName, queueMessage, visibilitytimeout, messageTimeToLive, timeout, this.client.version(), requestId, context); } /** @@ -173,12 +174,12 @@ public Mono enqueueWithRestResponseAsync(QueueMessage q * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono peekWithRestResponseAsync(Context context) { + public Mono peekWithRestResponseAsync(String queueName, Context context) { final Integer numberOfMessages = null; final Integer timeout = null; final String requestId = null; final String peekonly = "true"; - return service.peek(this.client.url(), numberOfMessages, timeout, this.client.version(), requestId, peekonly, context); + return service.peek(this.client.url(), queueName, numberOfMessages, timeout, this.client.version(), requestId, peekonly, context); } /** @@ -191,8 +192,8 @@ public Mono peekWithRestResponseAsync(Context context) { * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono peekWithRestResponseAsync(Integer numberOfMessages, Integer timeout, String requestId, Context context) { + public Mono peekWithRestResponseAsync(String queueName, Integer numberOfMessages, Integer timeout, String requestId, Context context) { final String peekonly = "true"; - return service.peek(this.client.url(), numberOfMessages, timeout, this.client.version(), requestId, peekonly, context); + return service.peek(this.client.url(), queueName, numberOfMessages, timeout, this.client.version(), requestId, peekonly, context); } } diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/QueuesImpl.java b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/QueuesImpl.java index 2eb2d4d1ec2e2..db933d31e4238 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/QueuesImpl.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/QueuesImpl.java @@ -11,6 +11,7 @@ import com.azure.core.annotations.HeaderParam; import com.azure.core.annotations.Host; import com.azure.core.annotations.HostParam; +import com.azure.core.annotations.PathParam; import com.azure.core.annotations.PUT; import com.azure.core.annotations.QueryParam; import com.azure.core.annotations.Service; @@ -25,10 +26,9 @@ import com.azure.storage.queue.models.QueuesSetMetadataResponse; import com.azure.storage.queue.models.SignedIdentifier; import com.azure.storage.queue.models.StorageErrorException; -import reactor.core.publisher.Mono; - import java.util.List; import java.util.Map; +import reactor.core.publisher.Mono; /** * An instance of this class provides access to all the operations defined in @@ -65,32 +65,32 @@ private interface QueuesService { @PUT("{queueName}") @ExpectedResponses({201, 204}) @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, @HeaderParam("x-ms-client-request-id") String requestId, Context context); + Mono create(@HostParam("url") String url, @PathParam("queueName") String queueName, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-meta-") Map metadata, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context); @DELETE("{queueName}") @ExpectedResponses({204}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono delete(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context); + Mono delete(@HostParam("url") String url, @PathParam("queueName") String queueName, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context); @GET("{queueName}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono getProperties(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, Context context); + Mono getProperties(@HostParam("url") String url, @PathParam("queueName") String queueName, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, Context context); @PUT("{queueName}") @ExpectedResponses({204}) @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, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, Context context); + Mono setMetadata(@HostParam("url") String url, @PathParam("queueName") String queueName, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-meta-") Map metadata, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, Context context); @GET("{queueName}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono getAccessPolicy(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, Context context); + Mono getAccessPolicy(@HostParam("url") String url, @PathParam("queueName") String queueName, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, Context context); @PUT("{queueName}") @ExpectedResponses({204}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono setAccessPolicy(@HostParam("url") String url, @BodyParam("application/xml; charset=utf-8") SignedIdentifiersWrapper queueAcl, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, Context context); + Mono setAccessPolicy(@HostParam("url") String url, @PathParam("queueName") String queueName, @BodyParam("application/xml; charset=utf-8") SignedIdentifiersWrapper queueAcl, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, Context context); } /** @@ -100,11 +100,11 @@ private interface QueuesService { * @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 queueName, Context context) { final Integer timeout = null; final Map metadata = null; final String requestId = null; - return service.create(this.client.url(), timeout, metadata, this.client.version(), requestId, context); + return service.create(this.client.url(), queueName, timeout, metadata, this.client.version(), requestId, context); } /** @@ -117,8 +117,8 @@ 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, String requestId, Context context) { - return service.create(this.client.url(), timeout, metadata, this.client.version(), requestId, context); + public Mono createWithRestResponseAsync(String queueName, Integer timeout, Map metadata, String requestId, Context context) { + return service.create(this.client.url(), queueName, timeout, metadata, this.client.version(), requestId, context); } /** @@ -128,10 +128,10 @@ public Mono createWithRestResponseAsync(Integer timeout, M * @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 queueName, Context context) { final Integer timeout = null; final String requestId = null; - return service.delete(this.client.url(), timeout, this.client.version(), requestId, context); + return service.delete(this.client.url(), queueName, timeout, this.client.version(), requestId, context); } /** @@ -143,8 +143,8 @@ 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(Integer timeout, String requestId, Context context) { - return service.delete(this.client.url(), timeout, this.client.version(), requestId, context); + public Mono deleteWithRestResponseAsync(String queueName, Integer timeout, String requestId, Context context) { + return service.delete(this.client.url(), queueName, timeout, this.client.version(), requestId, context); } /** @@ -154,11 +154,11 @@ public Mono deleteWithRestResponseAsync(Integer timeout, S * @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 queueName, Context context) { final Integer timeout = null; final String requestId = null; final String comp = "metadata"; - return service.getProperties(this.client.url(), timeout, this.client.version(), requestId, comp, context); + return service.getProperties(this.client.url(), queueName, timeout, this.client.version(), requestId, comp, context); } /** @@ -170,9 +170,9 @@ public Mono getPropertiesWithRestResponseAsync(Cont * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono getPropertiesWithRestResponseAsync(Integer timeout, String requestId, Context context) { + public Mono getPropertiesWithRestResponseAsync(String queueName, Integer timeout, String requestId, Context context) { final String comp = "metadata"; - return service.getProperties(this.client.url(), timeout, this.client.version(), requestId, comp, context); + return service.getProperties(this.client.url(), queueName, timeout, this.client.version(), requestId, comp, context); } /** @@ -182,12 +182,12 @@ public Mono getPropertiesWithRestResponseAsync(Inte * @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 queueName, Context context) { final Integer timeout = null; final Map metadata = null; final String requestId = null; final String comp = "metadata"; - return service.setMetadata(this.client.url(), timeout, metadata, this.client.version(), requestId, comp, context); + return service.setMetadata(this.client.url(), queueName, timeout, metadata, this.client.version(), requestId, comp, context); } /** @@ -200,9 +200,9 @@ public Mono setMetadataWithRestResponseAsync(Context * @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, String requestId, Context context) { + public Mono setMetadataWithRestResponseAsync(String queueName, Integer timeout, Map metadata, String requestId, Context context) { final String comp = "metadata"; - return service.setMetadata(this.client.url(), timeout, metadata, this.client.version(), requestId, comp, context); + return service.setMetadata(this.client.url(), queueName, timeout, metadata, this.client.version(), requestId, comp, context); } /** @@ -212,11 +212,11 @@ public Mono setMetadataWithRestResponseAsync(Integer * @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 queueName, Context context) { final Integer timeout = null; final String requestId = null; final String comp = "acl"; - return service.getAccessPolicy(this.client.url(), timeout, this.client.version(), requestId, comp, context); + return service.getAccessPolicy(this.client.url(), queueName, timeout, this.client.version(), requestId, comp, context); } /** @@ -228,9 +228,9 @@ public Mono getAccessPolicyWithRestResponseAsync( * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono getAccessPolicyWithRestResponseAsync(Integer timeout, String requestId, Context context) { + public Mono getAccessPolicyWithRestResponseAsync(String queueName, Integer timeout, String requestId, Context context) { final String comp = "acl"; - return service.getAccessPolicy(this.client.url(), timeout, this.client.version(), requestId, comp, context); + return service.getAccessPolicy(this.client.url(), queueName, timeout, this.client.version(), requestId, comp, context); } /** @@ -240,12 +240,12 @@ public Mono getAccessPolicyWithRestResponseAsync( * @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 queueName, Context context) { final Integer timeout = null; final String requestId = null; final String comp = "acl"; SignedIdentifiersWrapper queueAclConverted = new SignedIdentifiersWrapper(null); - return service.setAccessPolicy(this.client.url(), queueAclConverted, timeout, this.client.version(), requestId, comp, context); + return service.setAccessPolicy(this.client.url(), queueName, queueAclConverted, timeout, this.client.version(), requestId, comp, context); } /** @@ -258,9 +258,9 @@ public Mono setAccessPolicyWithRestResponseAsync( * @throws IllegalArgumentException thrown if parameters fail the validation. * @return a Mono which performs the network request upon subscription. */ - public Mono setAccessPolicyWithRestResponseAsync(List queueAcl, Integer timeout, String requestId, Context context) { + public Mono setAccessPolicyWithRestResponseAsync(String queueName, List queueAcl, Integer timeout, String requestId, Context context) { final String comp = "acl"; SignedIdentifiersWrapper queueAclConverted = new SignedIdentifiersWrapper(queueAcl); - return service.setAccessPolicy(this.client.url(), queueAclConverted, timeout, this.client.version(), requestId, comp, context); + return service.setAccessPolicy(this.client.url(), queueName, queueAclConverted, timeout, this.client.version(), requestId, comp, context); } } diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/ServicesImpl.java b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/ServicesImpl.java index dc353d45f5243..1dc20d2b42fa8 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/ServicesImpl.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/ServicesImpl.java @@ -25,9 +25,8 @@ import com.azure.storage.queue.models.ServicesSetPropertiesResponse; import com.azure.storage.queue.models.StorageErrorException; import com.azure.storage.queue.models.StorageServiceProperties; -import reactor.core.publisher.Mono; - import java.util.List; +import reactor.core.publisher.Mono; /** * An instance of this class provides access to all the operations defined in diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/DequeuedMessageItem.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/DequeuedMessage.java similarity index 85% rename from storage/client/queue/src/main/java/com/azure/storage/queue/models/DequeuedMessageItem.java rename to storage/client/queue/src/main/java/com/azure/storage/queue/models/DequeuedMessage.java index 7febd2c02758d..65e6e941c717a 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/DequeuedMessageItem.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/DequeuedMessage.java @@ -1,6 +1,5 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -// Code generated by Microsoft (R) AutoRest Code Generator. package com.azure.storage.queue.models; @@ -14,7 +13,7 @@ * on a Queue. */ @JacksonXmlRootElement(localName = "QueueMessage") -public final class DequeuedMessageItem { +public final class DequeuedMessage { /* * The Id of the Message. */ @@ -71,9 +70,9 @@ public String messageId() { * Set the messageId property: The Id of the Message. * * @param messageId the messageId value to set. - * @return the DequeuedMessageItem object itself. + * @return the DequeuedMessage object itself. */ - public DequeuedMessageItem messageId(String messageId) { + public DequeuedMessage messageId(String messageId) { this.messageId = messageId; return this; } @@ -96,9 +95,9 @@ public OffsetDateTime insertionTime() { * the Queue. * * @param insertionTime the insertionTime value to set. - * @return the DequeuedMessageItem object itself. + * @return the DequeuedMessage object itself. */ - public DequeuedMessageItem insertionTime(OffsetDateTime insertionTime) { + public DequeuedMessage insertionTime(OffsetDateTime insertionTime) { if (insertionTime == null) { this.insertionTime = null; } else { @@ -125,9 +124,9 @@ public OffsetDateTime expirationTime() { * and be automatically deleted. * * @param expirationTime the expirationTime value to set. - * @return the DequeuedMessageItem object itself. + * @return the DequeuedMessage object itself. */ - public DequeuedMessageItem expirationTime(OffsetDateTime expirationTime) { + public DequeuedMessage expirationTime(OffsetDateTime expirationTime) { if (expirationTime == null) { this.expirationTime = null; } else { @@ -153,9 +152,9 @@ public String popReceipt() { * been dequeued by another client. * * @param popReceipt the popReceipt value to set. - * @return the DequeuedMessageItem object itself. + * @return the DequeuedMessage object itself. */ - public DequeuedMessageItem popReceipt(String popReceipt) { + public DequeuedMessage popReceipt(String popReceipt) { this.popReceipt = popReceipt; return this; } @@ -178,9 +177,9 @@ public OffsetDateTime timeNextVisible() { * become visible in the Queue. * * @param timeNextVisible the timeNextVisible value to set. - * @return the DequeuedMessageItem object itself. + * @return the DequeuedMessage object itself. */ - public DequeuedMessageItem timeNextVisible(OffsetDateTime timeNextVisible) { + public DequeuedMessage timeNextVisible(OffsetDateTime timeNextVisible) { if (timeNextVisible == null) { this.timeNextVisible = null; } else { @@ -204,9 +203,9 @@ public long dequeueCount() { * dequeued. * * @param dequeueCount the dequeueCount value to set. - * @return the DequeuedMessageItem object itself. + * @return the DequeuedMessage object itself. */ - public DequeuedMessageItem dequeueCount(long dequeueCount) { + public DequeuedMessage dequeueCount(long dequeueCount) { this.dequeueCount = dequeueCount; return this; } @@ -224,9 +223,9 @@ public String messageText() { * Set the messageText property: The content of the Message. * * @param messageText the messageText value to set. - * @return the DequeuedMessageItem object itself. + * @return the DequeuedMessage object itself. */ - public DequeuedMessageItem messageText(String messageText) { + public DequeuedMessage messageText(String messageText) { this.messageText = messageText; return this; } diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesDequeueResponse.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesDequeueResponse.java index 4ab4b09a4a620..c08c7ccc025c7 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesDequeueResponse.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesDequeueResponse.java @@ -12,7 +12,7 @@ /** * Contains all response data for the dequeue operation. */ -public final class MessagesDequeueResponse extends ResponseBase> { +public final class MessagesDequeueResponse extends ResponseBase> { /** * Creates an instance of MessagesDequeueResponse. * @@ -22,7 +22,7 @@ public final class MessagesDequeueResponse extends ResponseBase value, MessagesDequeueHeaders headers) { + public MessagesDequeueResponse(HttpRequest request, int statusCode, HttpHeaders rawHeaders, List value, MessagesDequeueHeaders headers) { super(request, statusCode, rawHeaders, value, headers); } @@ -30,7 +30,7 @@ public MessagesDequeueResponse(HttpRequest request, int statusCode, HttpHeaders * @return the deserialized response body. */ @Override - public List value() { + public List value() { return super.value(); } } diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesPeekResponse.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesPeekResponse.java index 8ca8ed06fd99c..27ac646138908 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesPeekResponse.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesPeekResponse.java @@ -12,7 +12,7 @@ /** * Contains all response data for the peek operation. */ -public final class MessagesPeekResponse extends ResponseBase> { +public final class MessagesPeekResponse extends ResponseBase> { /** * Creates an instance of MessagesPeekResponse. * @@ -22,7 +22,7 @@ public final class MessagesPeekResponse extends ResponseBase value, MessagesPeekHeaders headers) { + public MessagesPeekResponse(HttpRequest request, int statusCode, HttpHeaders rawHeaders, List value, MessagesPeekHeaders headers) { super(request, statusCode, rawHeaders, value, headers); } @@ -30,7 +30,7 @@ public MessagesPeekResponse(HttpRequest request, int statusCode, HttpHeaders raw * @return the deserialized response body. */ @Override - public List value() { + public List value() { return super.value(); } } diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/PeekedMessageItem.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/PeekedMessage.java similarity index 85% rename from storage/client/queue/src/main/java/com/azure/storage/queue/models/PeekedMessageItem.java rename to storage/client/queue/src/main/java/com/azure/storage/queue/models/PeekedMessage.java index d86bdab8c2305..edc9960d2d747 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/PeekedMessageItem.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/PeekedMessage.java @@ -1,6 +1,5 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -// Code generated by Microsoft (R) AutoRest Code Generator. package com.azure.storage.queue.models; @@ -14,7 +13,7 @@ * on a Queue. */ @JacksonXmlRootElement(localName = "QueueMessage") -public final class PeekedMessageItem { +public final class PeekedMessage { /* * The Id of the Message. */ @@ -58,9 +57,9 @@ public String messageId() { * Set the messageId property: The Id of the Message. * * @param messageId the messageId value to set. - * @return the PeekedMessageItem object itself. + * @return the PeekedMessage object itself. */ - public PeekedMessageItem messageId(String messageId) { + public PeekedMessage messageId(String messageId) { this.messageId = messageId; return this; } @@ -83,9 +82,9 @@ public OffsetDateTime insertionTime() { * the Queue. * * @param insertionTime the insertionTime value to set. - * @return the PeekedMessageItem object itself. + * @return the PeekedMessage object itself. */ - public PeekedMessageItem insertionTime(OffsetDateTime insertionTime) { + public PeekedMessage insertionTime(OffsetDateTime insertionTime) { if (insertionTime == null) { this.insertionTime = null; } else { @@ -112,9 +111,9 @@ public OffsetDateTime expirationTime() { * and be automatically deleted. * * @param expirationTime the expirationTime value to set. - * @return the PeekedMessageItem object itself. + * @return the PeekedMessage object itself. */ - public PeekedMessageItem expirationTime(OffsetDateTime expirationTime) { + public PeekedMessage expirationTime(OffsetDateTime expirationTime) { if (expirationTime == null) { this.expirationTime = null; } else { @@ -138,9 +137,9 @@ public long dequeueCount() { * dequeued. * * @param dequeueCount the dequeueCount value to set. - * @return the PeekedMessageItem object itself. + * @return the PeekedMessage object itself. */ - public PeekedMessageItem dequeueCount(long dequeueCount) { + public PeekedMessage dequeueCount(long dequeueCount) { this.dequeueCount = dequeueCount; return this; } @@ -158,9 +157,9 @@ public String messageText() { * Set the messageText property: The content of the Message. * * @param messageText the messageText value to set. - * @return the PeekedMessageItem object itself. + * @return the PeekedMessage object itself. */ - public PeekedMessageItem messageText(String messageText) { + public PeekedMessage messageText(String messageText) { this.messageText = messageText; return this; } diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueProperties.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueProperties.java new file mode 100644 index 0000000000000..bb343ea96bd24 --- /dev/null +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueProperties.java @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.storage.queue.models; + +import java.util.Map; + +/** + * Model class containing properties of a specific queue in the storage Queue service. + */ +public final class QueueProperties { + private final Map metadata; + private final int approximateMessagesCount; + + /** + * Creates an instance that contains properties of a queue. + * + * @param metadata Metadata associated with the queue + * @param approximateMessagesCount Approximate number of messages contained in the queue + */ + public QueueProperties(Map metadata, int approximateMessagesCount) { + this.metadata = metadata; + this.approximateMessagesCount = approximateMessagesCount; + } + + /** + * @return the user-defined metadata associated with the queue + */ + public Map metadata() { + return this.metadata; + } + + /** + * @return the approximate number of messages contained in the queue at the time of properties retrieval + */ + public int approximateMessagesCount() { + return approximateMessagesCount; + } +} diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueuesSegmentOptions.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueuesSegmentOptions.java new file mode 100644 index 0000000000000..d58b2f71b8d05 --- /dev/null +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueuesSegmentOptions.java @@ -0,0 +1,89 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.storage.queue.models; + +import com.azure.storage.queue.QueueServiceAsyncClient; +import com.azure.storage.queue.QueueServiceClient; + +/** + * A set of options for selecting queues from Storage Queue service. + * + *
    + *
  • + * Providing {@link QueuesSegmentOptions#prefix() prefix} will filter {@link QueueItem queues} that begin + * with the prefix. + *
  • + *
  • + * Providing {@link QueuesSegmentOptions#maxResults() maxResults} will limit the number of {@link QueueItem queues} + * returned in a single page. + *
  • + *
  • + * Setting {@link QueuesSegmentOptions#includeMetadata() includeMetadata} to true will include the metadata of + * each {@link QueueItem queue}, if false {@link QueueItem#metadata() metadata} for each queue will be {@code null}. + *
  • + *
+ * + * @see QueueServiceClient + * @see QueueServiceAsyncClient + */ +public final class QueuesSegmentOptions { + private boolean includeMetadata; + + private String prefix; + + private Integer maxResults; + + /** + * @return the status of including metadata when listing queues + */ + public boolean includeMetadata() { + return includeMetadata; + } + + /** + * Sets the status of including queue metadata when listing queues + * + * @param includeMetadata Flag indicating if metadata should be included in the listing + * @return An updated QueuesSegmentOptions object + */ + public QueuesSegmentOptions includeMetadata(boolean includeMetadata) { + this.includeMetadata = includeMetadata; + return this; + } + + /** + * @return the prefix the queue name must match to be included in the listing + */ + public String prefix() { + return prefix; + } + + /** + * Sets the prefix that a queue must match to be included in the listing + * + * @param prefix The prefix that queues must start with to pass the filter + * @return An updated QueuesSegmentOptions object + */ + public QueuesSegmentOptions prefix(String prefix) { + this.prefix = prefix; + return this; + } + + /** + * @return the maximum number of queues to include in a single response + */ + public Integer maxResults() { + return maxResults; + } + + /** + * Sets the maximum number of queues to include in a single response + * + * @param maxResults Maximum number of results to include in a single response + * @return An updated QueuesSegmentOptions object + */ + public QueuesSegmentOptions maxResults(Integer maxResults) { + this.maxResults = maxResults; + return this; + } +} diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/UpdatedMessage.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/UpdatedMessage.java new file mode 100644 index 0000000000000..fa6a4d5970153 --- /dev/null +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/UpdatedMessage.java @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.storage.queue.models; + +import java.time.OffsetDateTime; + +/** + * Response from the service when updating a message. Contains the information needed to continue working with + * the specific message. + */ +public final class UpdatedMessage { + private final String popReceipt; + private final OffsetDateTime timeNextVisible; + + /** + * Creates an instance of updated message information. + * + * @param popReceipt Unique identifier that verifies the operation on a message is valid + * @param timeNextVisible The next time the message will be visible to other operations in the queue + */ + public UpdatedMessage(String popReceipt, OffsetDateTime timeNextVisible) { + this.popReceipt = popReceipt; + this.timeNextVisible = timeNextVisible; + } + + /** + * @return the unique identifier used to verify that the operation is allowed on the message + */ + public String popReceipt() { + return popReceipt; + } + + /** + * @return the next time the message will be visible to other operations in the queue + */ + public OffsetDateTime timeNextVisible() { + return timeNextVisible; + } +} diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/package-info.java b/storage/client/queue/src/main/java/com/azure/storage/queue/package-info.java new file mode 100644 index 0000000000000..e6671d8292fac --- /dev/null +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/package-info.java @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +/** + * This package contains the classes to perform actions on Azure Storage Queue. + */ +package com.azure.storage.queue; diff --git a/storage/client/queue/src/samples/java/com/azure/storage/queue/AsyncSamples.java b/storage/client/queue/src/samples/java/com/azure/storage/queue/AsyncSamples.java new file mode 100644 index 0000000000000..39cc17db37ca2 --- /dev/null +++ b/storage/client/queue/src/samples/java/com/azure/storage/queue/AsyncSamples.java @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.storage.queue; + +import static com.azure.storage.queue.SampleHelper.generateRandomName; + +/* + * This example mimics some arbitrary number of clients continuously sending messages up to a queue in a parallel and + * a server dequeuing the messages and processing them. + */ +public class AsyncSamples { + private static final String ACCOUNT_NAME = System.getenv("AZURE_STORAGE_ACCOUNT_NAME"); + private static final String SAS_TOKEN = System.getenv("PRIMARY_SAS_TOKEN"); + private static final String QUEUE_NAME = generateRandomName("async-call", 16); + + /** + * The main method shows how we do the basic operations of enqueueing and dequeueing messages on async queue client. + * @param args No args needed for main method. + */ + public static void main(String[] args) { + // Create an async queue client. + String queueURL = String.format("https://%s.queue.core.windows.net/%s%s", ACCOUNT_NAME, QUEUE_NAME, SAS_TOKEN); + QueueAsyncClient queueAsyncClient = new QueueClientBuilder().endpoint(queueURL).buildAsyncClient(); + + // Create a queue, enqueue two messages. + queueAsyncClient.create() + .doOnSuccess(response -> queueAsyncClient.enqueueMessage("This is message 1")) + .then(queueAsyncClient.enqueueMessage("This is message 2")) + .subscribe( + response -> { + System.out.println("Message successfully equeueed by queueAsyncClient. Message id:" + response.value().messageId()); + }, + err -> { + System.out.println("Error thrown when enqueue the message. Error message: " + err.getMessage()); + }, + () -> { + System.out.println("The enqueue has been completed."); + } + ); + } +} diff --git a/storage/client/queue/src/samples/java/com/azure/storage/queue/MessageSamples.java b/storage/client/queue/src/samples/java/com/azure/storage/queue/MessageSamples.java new file mode 100644 index 0000000000000..1372d45b9e808 --- /dev/null +++ b/storage/client/queue/src/samples/java/com/azure/storage/queue/MessageSamples.java @@ -0,0 +1,73 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.storage.queue; + +import com.azure.core.http.rest.Response; +import com.azure.storage.queue.models.DequeuedMessage; + +import java.time.Duration; + +import static com.azure.storage.queue.SampleHelper.generateRandomName; + +public class MessageSamples { + private static final String ACCOUNT_NAME = System.getenv("AZURE_STORAGE_ACCOUNT_NAME"); + private static final String SAS_TOKEN = System.getenv("PRIMARY_SAS_TOKEN"); + + /** + * The main method illustrate the basic operations for enqueue and dequeue messages using sync client. + * @param args No args needed for main method. + * @throws InterruptedException If the Thread.sleep operation gets interrupted. + */ + public static void main(String[] args) throws InterruptedException { + // Build Queue Client using SAS Token + String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", ACCOUNT_NAME, SAS_TOKEN); + QueueServiceClient queueServiceClient = new QueueServiceClientBuilder().endpoint(queueServiceURL).buildClient(); + + // Create a queue client + Response queueClientResponse = queueServiceClient.createQueue(generateRandomName("enqueue", 16)); + QueueClient queueClient = queueClientResponse.value(); + // Using queue client to enqueue several "Hello World" messages into queue. + for (int i = 0; i < 3; i++) { + queueClient.enqueueMessage("Hello World"); + } + + // Enqueue json file into message. + // TODO + + // Get the total count of msg in the queue + int count = queueClient.getProperties().value().approximateMessagesCount(); + + // Peek all messages in queue. It is supposed to print "Hello World" 3 times. + queueClient.peekMessages(count).forEach( + peekedMessage -> { + System.out.println("Here is the msg: " + peekedMessage.messageText()); + } + ); + + // Dequeue all messages in queue and update the message "Hello World" to Hello, world!" + queueClient.dequeueMessages(count, Duration.ZERO).forEach( + queueMessage -> { + String msgToReplace = String.format("Hello, world!"); + queueClient.updateMessage(queueMessage.messageId(), msgToReplace, queueMessage.popReceipt(), Duration.ZERO); + } + ); + + // Delete the first available msg. + // Since there is no invisible time for above dequeue, the following if condition should be true. + if (queueClient.dequeueMessages().iterator().hasNext()) { + DequeuedMessage queueMessage = queueClient.dequeueMessages().iterator().next(); + queueClient.deleteMessage(queueMessage.messageId(), queueMessage.popReceipt()); + } else { + System.out.println("OOps, the messages disappear!"); + } + + // Clear all messages in the queue + // Sleep to guarantee we skip the default invisible time. + Thread.sleep(500); + queueClient.clearMessages(); + + // Finally, we delete the queue. + queueClient.delete(); + } +} diff --git a/storage/client/queue/src/samples/java/com/azure/storage/queue/QueueExceptionSamples.java b/storage/client/queue/src/samples/java/com/azure/storage/queue/QueueExceptionSamples.java new file mode 100644 index 0000000000000..d0ee4c8f2aed4 --- /dev/null +++ b/storage/client/queue/src/samples/java/com/azure/storage/queue/QueueExceptionSamples.java @@ -0,0 +1,69 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.storage.queue; + +import com.azure.core.http.rest.Response; +import com.azure.storage.queue.models.StorageErrorCode; +import com.azure.storage.queue.models.StorageErrorException; + +import static com.azure.storage.queue.SampleHelper.generateRandomName; + +public class QueueExceptionSamples { + private static final String ACCOUNT_NAME = System.getenv("AZURE_STORAGE_ACCOUNT_NAME"); + private static final String SAS_TOKEN = System.getenv("PRIMARY_SAS_TOKEN"); + + /** + * The main method shows how to handle the storage exception. + * @param args No args needed for the main method. + * @throws RuntimeException If queueServiceClient failed to create a queue. + */ + public static void main(String[] args) { + // Create a queue service client. + String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", ACCOUNT_NAME, SAS_TOKEN); + QueueServiceClient queueServiceClient = new QueueServiceClientBuilder().endpoint(queueServiceURL).buildClient(); + + // Create queue client. + Response queueClientResponse; + try { + queueClientResponse = queueServiceClient.createQueue(generateRandomName("delete-not-exist", 16)); + System.out.println("Successfully create the queue! Status code: " + String.valueOf(queueClientResponse.statusCode())); + } catch (StorageErrorException e) { + System.out.println(String.format("Error creating a queue. Error message: %s", e.value().message())); + throw new RuntimeException(e); + } + QueueClient queueClient = queueClientResponse.value(); + queueClient.enqueueMessage("Hello, message 1!"); + queueClient.enqueueMessage("Hello, message 2!"); + + // Delete message with wrong message id. + try { + queueClientResponse.value().dequeueMessages().forEach( + msg -> { + queueClient.deleteMessage("wrong id", msg.popReceipt()); + } + ); + } catch (StorageErrorException e) { + if (e.getMessage().contains(StorageErrorCode.MESSAGE_NOT_FOUND.toString())) { + System.out.println("This is the error expected to throw"); + } else { + System.out.println("This is not the error we expect!"); + } + } + + // Delete message with wrong pop receipt. + try { + queueClient.dequeueMessages().forEach( + msg -> { + queueClient.deleteMessage(msg.messageId(), "Wrong Pop Receipt"); + } + ); + } catch (StorageErrorException e) { + if (e.getMessage().contains(StorageErrorCode.INVALID_QUERY_PARAMETER_VALUE.toString())) { + System.out.println("This is the error expected to throw"); + } else { + System.out.println("This is not the error we expect!"); + } + } + } +} diff --git a/storage/client/queue/src/samples/java/com/azure/storage/queue/QueueServiceSamples.java b/storage/client/queue/src/samples/java/com/azure/storage/queue/QueueServiceSamples.java new file mode 100644 index 0000000000000..ed1a9875a3d03 --- /dev/null +++ b/storage/client/queue/src/samples/java/com/azure/storage/queue/QueueServiceSamples.java @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.storage.queue; + +import static com.azure.storage.queue.SampleHelper.generateRandomName; + +public class QueueServiceSamples { + private static final String ACCOUNT_NAME = System.getenv("AZURE_STORAGE_ACCOUNT_NAME"); + private static final String SAS_TOKEN = System.getenv("PRIMARY_SAS_TOKEN"); + + /** + * The main method illustrated the basic operations of creating and deleting queues using queue service sync client. + * @param args No args needed for main method. + */ + public static void main(String[] args) { + // Build Queue Service Client using SAS Token + String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", ACCOUNT_NAME, SAS_TOKEN); + QueueServiceClient queueServiceClient = new QueueServiceClientBuilder().endpoint(queueServiceURL).buildClient(); + queueServiceClient.createQueue(generateRandomName("create-queue", 16)); + + // Create another queue and list all queues, print the name and then delete the queue. + queueServiceClient.createQueue(generateRandomName("create-extra", 16)); + queueServiceClient.listQueues().forEach( + queueItem -> { + System.out.println("The queue name is: " + queueItem.name()); + queueServiceClient.deleteQueue(queueItem.name()); + } + ); + } +} diff --git a/storage/client/queue/src/samples/java/com/azure/storage/queue/SampleHelper.java b/storage/client/queue/src/samples/java/com/azure/storage/queue/SampleHelper.java new file mode 100644 index 0000000000000..094a52026ffe6 --- /dev/null +++ b/storage/client/queue/src/samples/java/com/azure/storage/queue/SampleHelper.java @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.storage.queue; + +import java.util.UUID; + +class SampleHelper { + static String generateRandomName(String prefix, int length) { + int len = length > prefix.length() ? length - prefix.length() : 0; + return prefix + UUID.randomUUID().toString().substring(0, len); + } +} diff --git a/storage/client/queue/src/samples/java/com/azure/storage/queue/javadoc/QueueJavaDocCodeSamples.java b/storage/client/queue/src/samples/java/com/azure/storage/queue/javadoc/QueueJavaDocCodeSamples.java new file mode 100644 index 0000000000000..24b0405a49350 --- /dev/null +++ b/storage/client/queue/src/samples/java/com/azure/storage/queue/javadoc/QueueJavaDocCodeSamples.java @@ -0,0 +1,668 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.storage.queue.javadoc; + +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.queue.QueueAsyncClient; +import com.azure.storage.queue.QueueClient; +import com.azure.storage.queue.QueueClientBuilder; +import com.azure.storage.queue.models.AccessPolicy; +import com.azure.storage.queue.models.DequeuedMessage; +import com.azure.storage.queue.models.EnqueuedMessage; +import com.azure.storage.queue.models.QueueProperties; +import com.azure.storage.queue.models.SignedIdentifier; +import com.azure.storage.queue.models.UpdatedMessage; +import java.time.Duration; +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 QueueClient} and {@link QueueAsyncClient}. + */ + +public class QueueJavaDocCodeSamples { + /** + * Generates code sample for creating a {@link QueueClient}. + */ + public void buildQueueClient() { + // BEGIN: com.azure.storage.queue.queueClient.instantiation + QueueClient client = new QueueClientBuilder() + .connectionString("connectionstring") + .endpoint("endpoint") + .buildClient(); + // END: com.azure.storage.queue.queueClient.instantiation + } + + /** + * Generates code sample for creating a {@link QueueAsyncClient}. + */ + public void buildQueueAsyncClient() { + // BEGIN: com.azure.storage.queue.queueAsyncClient.instantiation + QueueAsyncClient client = new QueueClientBuilder() + .connectionString("connectionstring") + .endpoint("endpoint") + .buildAsyncClient(); + // END: com.azure.storage.queue.queueAsyncClient.instantiation + } + + /** + * Generates code sample for creating a {@link QueueClient} with {@link QueueClient} + * @return An instance of {@link QueueClient} + */ + public QueueClient createClientWithSASToken() { + // BEGIN: com.azure.storage.queue.queueClient.instantiation.sastoken + QueueClient queueClient = new QueueClientBuilder() + .endpoint("https://${accountName}.queue.core.windows.net?${SASToken}") + .buildClient(); + // END: com.azure.storage.queue.queueClient.instantiation.sastoken + return queueClient; + } + + /** + * Generates code sample for creating a {@link QueueAsyncClient} with {@link SASTokenCredential} + * @return An instance of {@link QueueAsyncClient} + */ + public QueueAsyncClient createAsyncClientWithSASToken() { + // BEGIN: com.azure.storage.queue.queueAsyncClient.instantiation.sastoken + QueueAsyncClient queueAsyncClient = new QueueClientBuilder() + .endpoint("https://{accountName}.queue.core.windows.net?{SASToken}") + .buildAsyncClient(); + // END: com.azure.storage.queue.queueAsyncClient.instantiation.sastoken + return queueAsyncClient; + } + + /** + * Generates code sample for creating a {@link QueueClient} with {@link SASTokenCredential} + * @return An instance of {@link QueueClient} + */ + public QueueClient createClientWithCredential() { + // BEGIN: com.azure.storage.queue.queueClient.instantiation.credential + QueueClient queueClient = new QueueClientBuilder() + .endpoint("https://${accountName}.queue.core.windows.net") + .queueName("myqueue") + .credential(SASTokenCredential.fromQuery("{SASTokenQueryParams}")) + .buildClient(); + // END: com.azure.storage.queue.queueClient.instantiation.credential + return queueClient; + } + + /** + * Generates code sample for creating a {@link QueueAsyncClient} with {@link SASTokenCredential} + * @return An instance of {@link QueueAsyncClient} + */ + public QueueAsyncClient createAsyncClientWithCredential() { + // BEGIN: com.azure.storage.queue.queueAsyncClient.instantiation.credential + QueueAsyncClient queueAsyncClient = new QueueClientBuilder() + .endpoint("https://{accountName}.queue.core.windows.net") + .queueName("myqueue") + .credential(SASTokenCredential.fromQuery("{SASTokenQueryParams}")) + .buildAsyncClient(); + // END: com.azure.storage.queue.queueAsyncClient.instantiation.credential + return queueAsyncClient; + } + + /** + * Generates code sample for creating a {@link QueueClient} with {@code connectionString} which turns into {@link SharedKeyCredential} + * @return An instance of {@link QueueClient} + */ + public QueueClient createClientWithConnectionString() { + // BEGIN: com.azure.storage.queue.queueClient.instantiation.connectionstring + String connectionString = "DefaultEndpointsProtocol=https;AccountName={name};" + + "AccountKey={key};EndpointSuffix={core.windows.net}"; + QueueClient queueClient = new QueueClientBuilder() + .connectionString(connectionString) + .buildClient(); + // END: com.azure.storage.queue.queueClient.instantiation.connectionstring + return queueClient; + } + + /** + * Generates code sample for creating a {@link QueueAsyncClient} with {@code connectionString} which turns into {@link SharedKeyCredential} + * @return An instance of {@link QueueAsyncClient} + */ + public QueueAsyncClient createAsyncClientWithConnectionString() { + // BEGIN: com.azure.storage.queue.queueAsyncClient.instantiation.connectionstring + String connectionString = "DefaultEndpointsProtocol=https;AccountName={name};" + + "AccountKey={key};EndpointSuffix={core.windows.net}"; + QueueAsyncClient queueAsyncClient = new QueueClientBuilder() + .connectionString(connectionString) + .buildAsyncClient(); + // END: com.azure.storage.queue.queueAsyncClient.instantiation.connectionstring + return queueAsyncClient; + } + + /** + * Generates a code sample for using {@link QueueClient#create()} + */ + public void createQueue() { + QueueClient queueClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueClient.create + VoidResponse response = queueClient.create(); + System.out.println("Complete creating queue with status code: " + response.statusCode()); + // END: com.azure.storage.queue.queueClient.create + } + + /** + * Generates a code sample for using {@link QueueAsyncClient#create()} + */ + public void createQueueAsync() { + QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueAsyncClient.create + queueAsyncClient.create().subscribe( + response -> { }, + error -> System.err.print(error.toString()), + () -> System.out.println("Complete creating the queue!") + ); + // END: com.azure.storage.queue.queueAsyncClient.create + } + + /** + * Generates a code sample for using {@link QueueClient#create(Map)} + */ + public void createQueueMaxOverload() { + QueueClient queueClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueClient.create#map + VoidResponse response = queueClient.create(Collections.singletonMap("queue", "metadataMap")); + System.out.println("Complete creating queue with status code: " + response.statusCode()); + // END: com.azure.storage.queue.queueClient.create#map + } + + /** + * Generates a code sample for using {@link QueueAsyncClient#create(Map)} + */ + public void createQueueAsyncMaxOverload() { + QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueAsyncClient.create#map + queueAsyncClient.create(Collections.singletonMap("queue", "metadataMap")).subscribe( + response -> { }, + error -> System.err.print(error.toString()), + () -> System.out.println("Complete creating the queue!") + ); + // END: com.azure.storage.queue.queueAsyncClient.create#map + } + + /** + * Generates a code sample for using {@link QueueClient#enqueueMessage(String)} + */ + public void enqueueMessage() { + QueueClient queueClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueClient.enqueueMessage#string + Response response = queueClient.enqueueMessage("hello msg"); + System.out.println("Complete enqueuing the message with status code: " + response.statusCode()); + // END: com.azure.storage.queue.queueClient.enqueueMessage#string + } + + /** + * Generates a code sample for using {@link QueueAsyncClient#enqueueMessage(String)} + */ + public void enqueueMessageAsync() { + QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueAsyncClient.enqueueMessage#string + queueAsyncClient.enqueueMessage("Hello, Azure").subscribe( + response -> { }, + error -> System.err.print(error.toString()), + () -> System.out.println("Complete enqueuing the message!") + ); + // END: com.azure.storage.queue.queueAsyncClient.enqueueMessage#string + } + + /** + * Generates a code sample for using {@link QueueClient#enqueueMessage(String, Duration, Duration)} + */ + public void enqueueMessageWithTimeoutOverload() { + QueueClient queueClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueClient.enqueueMessage#string-duration-duration + EnqueuedMessage enqueuedMessage = queueClient.enqueueMessage("Hello, Azure", + Duration.ofSeconds(5), null).value(); + System.out.printf("Message %s expires at %s", enqueuedMessage.messageId(), enqueuedMessage.expirationTime()); + // END: com.azure.storage.queue.queueClient.enqueueMessage#string-duration-duration + } + + /** + * Generates a code sample for using {@link QueueAsyncClient#enqueueMessage(String, Duration, Duration)} + */ + public void enqueueMessageAsyncWithTimeoutOverload() { + QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueAsyncClient.enqueueMessage#string-duration-duration + queueAsyncClient.enqueueMessage("Hello, Azure", + Duration.ofSeconds(5), null).subscribe( + response -> System.out.printf("Message %s expires at %s", response.value().messageId(), + response.value().expirationTime()), + error -> System.err.print(error.toString()), + () -> System.out.println("Complete enqueuing the message!") + ); + // END: com.azure.storage.queue.queueAsyncClient.enqueueMessage#string-duration-duration + } + + /** + * Generates a code sample for using {@link QueueClient#enqueueMessage(String, Duration, Duration)} + */ + public void enqueueMessageWithLiveTimeOverload() { + QueueClient queueClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueClient.enqueueMessageLiveTime#string-duration-duration + EnqueuedMessage enqueuedMessage = queueClient.enqueueMessage("Goodbye, Azure", + null, Duration.ofSeconds(5)).value(); + System.out.printf("Message %s expires at %s", enqueuedMessage.messageId(), enqueuedMessage.expirationTime()); + // END: com.azure.storage.queue.queueClient.enqueueMessageLiveTime#string-duration-duration + } + + /** + * Generates a code sample for using {@link QueueAsyncClient#enqueueMessage(String, Duration, Duration)} + */ + public void enqueueMessageAsyncWithLiveTimeOverload() { + QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueAsyncClient.enqueueMessageLiveTime#string-duration-duration + queueAsyncClient.enqueueMessage("Goodbye, Azure", + null, Duration.ofSeconds(5)).subscribe( + response -> System.out.printf("Message %s expires at %s", response.value().messageId(), + response.value().expirationTime()), + error -> System.err.print(error.toString()), + () -> System.out.println("Complete enqueuing the message!") + ); + // END: com.azure.storage.queue.queueAsyncClient.enqueueMessageLiveTime#string-duration-duration + } + + /** + * Generates a code sample for using {@link QueueClient#dequeueMessages()} + */ + public void dequeueMessage() { + QueueClient queueClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueClient.dequeueMessages + queueClient.dequeueMessages().forEach( + dequeuedMessage -> { + System.out.println("Complete dequeuing the message: " + dequeuedMessage.messageText()); + } + ); + // END: com.azure.storage.queue.queueClient.dequeueMessages + } + + + /** + * Generates a code sample for using {@link QueueAsyncClient#dequeueMessages()} + */ + public void dequeueMessageAsync() { + QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueAsyncClient.dequeueMessages + queueAsyncClient.dequeueMessages().subscribe( + dequeuedMessage -> System.out.println("The message got from dequeue operation: " + + dequeuedMessage.messageText()), + error -> System.err.print(error.toString()), + () -> System.out.println("Complete dequeuing the message!") + ); + // END: com.azure.storage.queue.queueAsyncClient.dequeueMessages + } + + /** + * Generates a code sample for using {@link QueueClient#dequeueMessages(Integer)} + */ + public void dequeueMessageWithOverload() { + QueueClient queueClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueClient.dequeueMessages#integer + for (DequeuedMessage dequeuedMessage : queueClient.dequeueMessages(5)) { + System.out.printf("Dequeued %s and it becomes visible at %s", + dequeuedMessage.messageId(), dequeuedMessage.timeNextVisible()); + } + // END: com.azure.storage.queue.queueClient.dequeueMessages#integer + } + + /** + * Generates a code sample for using {@link QueueAsyncClient#dequeueMessages(Integer)} + */ + public void dequeueMessageAsyncWithOverload() { + QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueAsyncClient.dequeueMessages#integer + queueAsyncClient.dequeueMessages(5).subscribe( + dequeuedMessage -> System.out.println("The message got from dequeue operation: " + + dequeuedMessage.messageText()), + error -> System.err.print(error.toString()), + () -> System.out.println("Complete dequeuing the message!") + ); + // END: com.azure.storage.queue.queueAsyncClient.dequeueMessages#integer + } + + /** + * Generates a code sample for using {@link QueueClient#dequeueMessages(Integer, Duration)} + */ + public void dequeueMessageMaxOverload() { + QueueClient queueClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueClient.dequeueMessages#integer-duration + for (DequeuedMessage dequeuedMessage : queueClient.dequeueMessages(5, Duration.ofSeconds(60))) { + System.out.printf("Dequeued %s and it becomes visible at %s", + dequeuedMessage.messageId(), dequeuedMessage.timeNextVisible()); + } + // END: com.azure.storage.queue.queueClient.dequeueMessages#integer-duration + } + + /** + * Generates a code sample for using {@link QueueAsyncClient#dequeueMessages(Integer, Duration)} + */ + public void dequeueMessageAsyncMaxOverload() { + QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueAsyncClient.dequeueMessages#integer-duration + queueAsyncClient.dequeueMessages(5, Duration.ofSeconds(60)).subscribe( + dequeuedMessage -> System.out.println("The message got from dequeue operation: " + + dequeuedMessage.messageText()), + error -> System.err.print(error.toString()), + () -> System.out.println("Complete dequeuing the message!") + ); + // END: com.azure.storage.queue.queueAsyncClient.dequeueMessages#integer-duration + } + + /** + * Generates a code sample for using {@link QueueClient#peekMessages()} + */ + public void peekMessage() { + QueueClient queueClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueClient.peekMessages + queueClient.peekMessages().forEach( + peekedMessage -> { + System.out.println("Complete peeking the message: " + peekedMessage.messageText()); + } + ); + // END: com.azure.storage.queue.queueClient.peekMessages + } + + + /** + * Generates a code sample for using {@link QueueAsyncClient#peekMessages()} + */ + public void peekMessageAsync() { + QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueAsyncClient.peekMessages + queueAsyncClient.peekMessages().subscribe( + peekMessages -> System.out.println("The message got from peek operation: " + peekMessages.messageText()), + error -> System.err.print(error.toString()), + () -> System.out.println("Complete peeking the message!") + ); + // END: com.azure.storage.queue.queueAsyncClient.peekMessages + } + + /** + * Generates a code sample for using {@link QueueClient#peekMessages(Integer)} + */ + public void peekMessageMaxOverload() { + QueueClient queueClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueClient.peekMessages#integer + queueClient.peekMessages(5).forEach( + peekMessage -> System.out.printf("Peeked message %s has been dequeued %d times", + peekMessage.messageId(), peekMessage.dequeueCount()) + ); + // END: com.azure.storage.queue.queueClient.peekMessages#integer + } + + + /** + * Generates a code sample for using {@link QueueAsyncClient#peekMessages(Integer)} + */ + public void peekMessageAsyncMaxOverload() { + QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueAsyncClient.peekMessages#integer + queueAsyncClient.peekMessages(5).subscribe( + peekMessage -> System.out.printf("Peeked message %s has been dequeued %d times", + peekMessage.messageId(), peekMessage.dequeueCount()), + error -> System.err.print(error.toString()), + () -> System.out.println("Complete peeking the message!") + ); + // END: com.azure.storage.queue.queueAsyncClient.peekMessages#integer + } + + /** + * Generates a code sample for using {@link QueueClient#updateMessage(String, String, String, Duration)} + */ + public void updateMessage() { + QueueClient queueClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueClient.updateMessage + queueClient.dequeueMessages().forEach( + dequeuedMessage -> { + Response response = queueClient.updateMessage("newText", + dequeuedMessage.messageId(), dequeuedMessage.popReceipt(), null); + System.out.println("Complete updating the message with status code " + response.statusCode()); + } + ); + // END: com.azure.storage.queue.queueClient.updateMessage + } + + + /** + * Generates a code sample for using {@link QueueAsyncClient#updateMessage(String, String, String, Duration)} + */ + public void updateMessageAsync() { + QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueAsyncClient.updateMessage + queueAsyncClient.dequeueMessages().subscribe( + dequeuedMessage -> { + queueAsyncClient.updateMessage("newText", dequeuedMessage.messageId(), + dequeuedMessage.popReceipt(), null).subscribe( + response -> { }, + updateError -> System.err.print(updateError.toString()), + () -> System.out.println("Complete updating the message!") + ); + }, + dequeueError -> System.err.print(dequeueError.toString()), + () -> System.out.println("Complete dequeueing the message!") + ); + // END: com.azure.storage.queue.queueAsyncClient.updateMessage + } + + /** + * Generates a code sample for using {@link QueueClient#deleteMessage(String, String)} + */ + public void deleteMessage() { + QueueClient queueClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueClient.deleteMessage + queueClient.dequeueMessages().forEach( + dequeuedMessage -> { + VoidResponse response = queueClient.deleteMessage(dequeuedMessage.messageId(), + dequeuedMessage.popReceipt()); + System.out.println("Complete deleting the message with status code " + response.statusCode()); + } + ); + // END: com.azure.storage.queue.queueClient.deleteMessage + } + + + /** + * Generates a code sample for using {@link QueueAsyncClient#deleteMessage(String, String)} + */ + public void deleteMessageAsync() { + QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueAsyncClient.deleteMessage + queueAsyncClient.dequeueMessages().subscribe( + dequeuedMessage -> { + queueAsyncClient.deleteMessage(dequeuedMessage.messageId(), dequeuedMessage.popReceipt()).subscribe( + response -> { }, + deleteError -> System.err.print(deleteError.toString()), + () -> System.out.println("Complete deleting the message!") + ); + }, + dequeueError -> System.err.print(dequeueError.toString()), + () -> System.out.println("Complete dequeueing the message!") + ); + // END: com.azure.storage.queue.queueAsyncClient.deleteMessage + } + + /** + * Generates a code sample for using {@link QueueClient#delete()} + */ + public void deleteQueue() { + QueueClient queueClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueClient.delete + VoidResponse response = queueClient.delete(); + System.out.println("Complete deleting the queue with status code: " + response.statusCode()); + // END: com.azure.storage.queue.queueClient.delete + } + + + /** + * Generates a code sample for using {@link QueueAsyncClient#delete()} + */ + public void deleteQueueAsync() { + QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueAsyncClient.delete + queueAsyncClient.delete().subscribe( + response -> System.out.println("Deleting the queue completed with status code: " + response.statusCode()) + ); + // END: com.azure.storage.queue.queueAsyncClient.delete + } + + /** + * Generates a code sample for using {@link QueueClient#getProperties()} + */ + public void getProperties() { + QueueClient queueClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueClient.getProperties + QueueProperties properties = queueClient.getProperties().value(); + System.out.printf("Metadata: %s, Approximate message count: %d", properties.metadata(), + properties.approximateMessagesCount()); + // END: com.azure.storage.queue.queueClient.getProperties + } + + /** + * Generates a code sample for using {@link QueueAsyncClient#getProperties()} + */ + public void getPropertiesAsync() { + QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueAsyncClient.getProperties + queueAsyncClient.getProperties() + .subscribe(response -> { + QueueProperties properties = response.value(); + System.out.printf("Metadata: %s, Approximate message count: %d", properties.metadata(), + properties.approximateMessagesCount()); + }); + // END: com.azure.storage.queue.queueAsyncClient.getProperties + } + + /** + * Generate a code sample for using {@link QueueClient#setMetadata(Map)} to set metadata. + */ + public void setMetadata() { + QueueClient queueClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueClient.setMetadata#map + VoidResponse response = queueClient.setMetadata(Collections.singletonMap("queue", "metadataMap")); + System.out.printf("Setting metadata completed with status code %d", response.statusCode()); + // END: com.azure.storage.queue.queueClient.setMetadata#map + } + + /** + * Generate a code sample for using {@link QueueAsyncClient#setMetadata(Map)} to set metadata. + */ + public void setMetadataAsync() { + QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueAsyncClient.setMetadata#map + queueAsyncClient.setMetadata(Collections.singletonMap("queue", "metadataMap")) + .subscribe(response -> System.out.printf("Setting metadata completed with status code %d", + response.statusCode())); + // END: com.azure.storage.queue.queueAsyncClient.setMetadata#map + } + + /** + * Generate a code sample for using {@link QueueClient#setMetadata(Map)} to clear metadata. + */ + public void clearMetadata() { + QueueClient queueClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueClient.clearMetadata#map + VoidResponse response = queueClient.setMetadata(null); + System.out.printf("Clearing metadata completed with status code %d", response.statusCode()); + // END: com.azure.storage.queue.queueClient.clearMetadata#map + } + + /** + * Generate a code sample for using {@link QueueAsyncClient#setMetadata(Map)} to clear metadata. + */ + public void clearMetadataAsync() { + QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueAsyncClient.clearMetadata#map + queueAsyncClient.setMetadata(null) + .subscribe(response -> System.out.printf("Clearing metadata completed with status code %d", + response.statusCode())); + // END: com.azure.storage.queue.queueAsyncClient.clearMetadata#map + } + + /** + * Generates a code sample for using {@link QueueClient#getAccessPolicy()} + */ + public void getAccessPolicy() { + QueueClient queueClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueClient.getAccessPolicy + for (SignedIdentifier permission : queueClient.getAccessPolicy()) { + System.out.printf("Access policy %s allows these permissions: %s", permission.id(), + permission.accessPolicy().permission()); + } + // END: com.azure.storage.queue.queueClient.getAccessPolicy + } + + /** + * Generates a code sample for using {@link QueueAsyncClient#getAccessPolicy()} + */ + public void getAccessPolicyAsync() { + QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueAsyncClient.getAccessPolicy + queueAsyncClient.getAccessPolicy() + .subscribe(result -> System.out.printf("Access policy %s allows these permissions: %s", + result.id(), result.accessPolicy().permission())); + // END: com.azure.storage.queue.queueAsyncClient.getAccessPolicy + } + + /** + * Generates a code sample for using {@link QueueClient#setAccessPolicy(List)} + */ + public void setAccessPolicy() { + QueueClient queueClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueClient.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); + VoidResponse response = queueClient.setAccessPolicy(Collections.singletonList(permission)); + System.out.printf("Setting access policies completed with status code %d", response.statusCode()); + // END: com.azure.storage.queue.queueClient.setAccessPolicy + } + + /** + * Generates a code sample for using {@link QueueAsyncClient#setAccessPolicy(List)} + */ + public void setAccessPolicyAsync() { + QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueAsyncClient.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); + queueAsyncClient.setAccessPolicy(Collections.singletonList(permission)) + .subscribe(response -> System.out.printf("Setting access policies completed with status code %d", + response.statusCode())); + // END: com.azure.storage.queue.queueAsyncClient.setAccessPolicy + } + + /** + * Generates a code sample for using {@link QueueClient#clearMessages()} + */ + public void clearMessages() { + QueueClient queueClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueClient.clearMessages + VoidResponse response = queueClient.clearMessages(); + System.out.printf("Clearing messages completed with status code %d", response.statusCode()); + // END: com.azure.storage.queue.queueClient.clearMessages + } + + + /** + * Generates a code sample for using {@link QueueAsyncClient#clearMessages()} + */ + public void clearMessagesAsync() { + QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueAsyncClient.clearMessages + queueAsyncClient.clearMessages().subscribe( + response -> System.out.println("Clearing messages completed with status code: " + response.statusCode()) + ); + // END: com.azure.storage.queue.queueAsyncClient.clearMessages + } + +} diff --git a/storage/client/queue/src/samples/java/com/azure/storage/queue/javadoc/QueueServiceJavaDocCodeSamples.java b/storage/client/queue/src/samples/java/com/azure/storage/queue/javadoc/QueueServiceJavaDocCodeSamples.java new file mode 100644 index 0000000000000..3ed03621fbf76 --- /dev/null +++ b/storage/client/queue/src/samples/java/com/azure/storage/queue/javadoc/QueueServiceJavaDocCodeSamples.java @@ -0,0 +1,369 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.storage.queue.javadoc; + +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.queue.QueueClient; +import com.azure.storage.queue.QueueServiceAsyncClient; +import com.azure.storage.queue.QueueServiceClient; +import com.azure.storage.queue.QueueServiceClientBuilder; +import com.azure.storage.queue.models.QueuesSegmentOptions; +import com.azure.storage.queue.models.StorageServiceProperties; +import com.azure.storage.queue.models.StorageServiceStats; +import java.util.Collections; +import java.util.Map; + +/** + * Contains code snippets when generating javadocs through doclets for {@link QueueServiceClient} and {@link QueueServiceAsyncClient}. + */ +public class QueueServiceJavaDocCodeSamples { + /** + * Generates code sample for creating a {@link QueueServiceClient}. + */ + public void buildQueueServiceClient() { + // BEGIN: com.azure.storage.queue.queueServiceClient.instantiation + QueueServiceClient client = new QueueServiceClientBuilder() + .connectionString("connectionstring") + .endpoint("endpoint") + .buildClient(); + // END: com.azure.storage.queue.queueServiceClient.instantiation + } + + /** + * Generates code sample for creating a {@link QueueServiceAsyncClient}. + */ + public void buildQueueServiceAsyncClient() { + // BEGIN: com.azure.storage.queue.queueServiceAsyncClient.instantiation + QueueServiceAsyncClient client = new QueueServiceClientBuilder() + .connectionString("connectionstring") + .endpoint("endpoint") + .buildAsyncClient(); + // END: com.azure.storage.queue.queueServiceAsyncClient.instantiation + } + + /** + * Generates code sample for creating a {@link QueueServiceClient} with {@link SASTokenCredential} + * @return An instance of {@link QueueServiceClient} + */ + public QueueServiceClient createClientWithSASToken() { + // BEGIN: com.azure.storage.queue.queueServiceClient.instantiation.sastoken + QueueServiceClient queueServiceClient = new QueueServiceClientBuilder() + .endpoint("https://${accountName}.queue.core.windows.net?${SASToken}") + .buildClient(); + // END: com.azure.storage.queue.queueServiceClient.instantiation.sastoken + return queueServiceClient; + } + + /** + * Generates code sample for creating a {@link QueueServiceAsyncClient} with {@link SASTokenCredential} + * @return An instance of {@link QueueServiceAsyncClient} + */ + public QueueServiceAsyncClient createAsyncClientWithSASToken() { + // BEGIN: com.azure.storage.queue.queueServiceAsyncClient.instantiation.sastoken + QueueServiceAsyncClient queueServiceAsyncClient = new QueueServiceClientBuilder() + .endpoint("https://{accountName}.queue.core.windows.net?{SASToken}") + .buildAsyncClient(); + // END: com.azure.storage.queue.queueServiceAsyncClient.instantiation.sastoken + return queueServiceAsyncClient; + } + + /** + * Generates code sample for creating a {@link QueueServiceClient} with {@link SASTokenCredential} + * @return An instance of {@link QueueServiceClient} + */ + public QueueServiceClient createClientWithCredential() { + // BEGIN: com.azure.storage.queue.queueServiceClient.instantiation.credential + QueueServiceClient queueServiceClient = new QueueServiceClientBuilder() + .endpoint("https://${accountName}.queue.core.windows.net") + .credential(SASTokenCredential.fromQuery("{SASTokenQueryParams}")) + .buildClient(); + // END: com.azure.storage.queue.queueServiceClient.instantiation.credential + return queueServiceClient; + } + + /** + * Generates code sample for creating a {@link QueueServiceAsyncClient} with {@link SASTokenCredential} + * @return An instance of {@link QueueServiceAsyncClient} + */ + public QueueServiceAsyncClient createAsyncClientWithCredential() { + // BEGIN: com.azure.storage.queue.queueServiceAsyncClient.instantiation.credential + QueueServiceAsyncClient queueServiceAsyncClient = new QueueServiceClientBuilder() + .endpoint("https://{accountName}.queue.core.windows.net") + .credential(SASTokenCredential.fromQuery("{SASTokenQueryParams}")) + .buildAsyncClient(); + // END: com.azure.storage.queue.queueServiceAsyncClient.instantiation.credential + return queueServiceAsyncClient; + } + + /** + * Generates code sample for creating a {@link QueueServiceClient} with {@code connectionString} which turns into {@link SharedKeyCredential} + * @return An instance of {@link QueueServiceClient} + */ + public QueueServiceClient createClientWithConnectionString() { + // BEGIN: com.azure.storage.queue.queueServiceClient.instantiation.connectionstring + String connectionString = "DefaultEndpointsProtocol=https;AccountName={name};" + + "AccountKey={key};EndpointSuffix={core.windows.net}"; + QueueServiceClient queueServiceClient = new QueueServiceClientBuilder() + .connectionString(connectionString) + .buildClient(); + // END: com.azure.storage.queue.queueServiceClient.instantiation.connectionstring + return queueServiceClient; + } + + /** + * Generates code sample for creating a {@link QueueServiceAsyncClient} with {@code connectionString} which turns into {@link SharedKeyCredential} + * @return An instance of {@link QueueServiceAsyncClient} + */ + public QueueServiceAsyncClient createAsyncClientWithConnectionString() { + // BEGIN: com.azure.storage.queue.queueServiceAsyncClient.instantiation.connectionstring + String connectionString = "DefaultEndpointsProtocol=https;AccountName={name};" + + "AccountKey={key};EndpointSuffix={core.windows.net}"; + QueueServiceAsyncClient queueServiceAsyncClient = new QueueServiceClientBuilder() + .connectionString(connectionString) + .buildAsyncClient(); + // END: com.azure.storage.queue.queueServiceAsyncClient.instantiation.connectionstring + return queueServiceAsyncClient; + } + + /** + * Generates a code sample for using {@link QueueServiceClient#createQueue(String)} + */ + public void createQueue() { + QueueServiceClient queueServiceClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueServiceClient.createQueue#string + Response response = queueServiceClient.createQueue("myqueue"); + System.out.println("Complete creating queue with status code: " + response.statusCode()); + // END: com.azure.storage.queue.queueServiceClient.createQueue#string + } + + /** + * Generates a code sample for using {@link QueueServiceAsyncClient#createQueue(String)} + */ + public void createQueueAsync() { + QueueServiceAsyncClient queueServiceAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueServiceAsyncClient.createQueue#string + queueServiceAsyncClient.createQueue("myqueue").subscribe( + response -> { }, + error -> System.err.print(error.toString()), + () -> System.out.println("Complete creating the queue!") + ); + // END: com.azure.storage.queue.queueServiceAsyncClient.createQueue#string + } + + /** + * Generates a code sample for using {@link QueueServiceClient#createQueue(String, Map)} + */ + public void createQueueMaxOverload() { + QueueServiceClient queueServiceClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueServiceClient.createQueue#string-map + Response response = queueServiceClient.createQueue("myqueue", + Collections.singletonMap("queue", "metadata")); + System.out.println("Complete creating queue with status code: " + response.statusCode()); + // END: com.azure.storage.queue.queueServiceClient.createQueue#string-map + } + + /** + * Generates a code sample for using {@link QueueServiceAsyncClient#createQueue(String, Map)} + */ + public void createQueueAsyncMaxOverload() { + QueueServiceAsyncClient queueServiceAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueServiceAsyncClient.createQueue#string-map + queueServiceAsyncClient.createQueue("myqueue", Collections.singletonMap("queue", "metadata")) + .subscribe( + response -> System.out.printf("Creating the queue with status code %d", response.statusCode()), + error -> System.err.print(error.toString()), + () -> System.out.println("Complete creating the queue!") + ); + // END: com.azure.storage.queue.queueServiceAsyncClient.createQueue#string-map + } + + /** + * Generates a code sample for using {@link QueueServiceClient#listQueues()} + */ + public void listQueues() { + QueueServiceClient queueServiceClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueServiceClient.listQueues + queueServiceClient.listQueues().forEach( + queueItem -> System.out.printf("Queue %s exists in the account", queueItem.name()) + ); + // END: com.azure.storage.queue.queueServiceClient.listQueues + } + + /** + * Generates a code sample for using {@link QueueServiceAsyncClient#listQueues()} + */ + public void listQueuesAsync() { + QueueServiceAsyncClient queueServiceAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueServiceAsyncClient.listQueues + queueServiceAsyncClient.listQueues().subscribe( + queueItem -> System.out.printf("Queue %s exists in the account", queueItem.name()), + error -> System.err.print(error.toString()), + () -> System.out.println("Complete listing the queues!") + ); + // END: com.azure.storage.queue.queueServiceAsyncClient.listQueues + } + + /** + * Generates a code sample for using {@link QueueServiceClient#listQueues(QueuesSegmentOptions)} )} + */ + public void listQueuesWithOverload() { + QueueServiceClient queueServiceClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueServiceClient.listQueues#queueSergmentOptions + queueServiceClient.listQueues(new QueuesSegmentOptions().prefix("azure")).forEach( + queueItem -> System.out.printf("Queue %s exists in the account and has metadata %s", + queueItem.name(), queueItem.metadata()) + ); + // END: com.azure.storage.queue.queueServiceClient.listQueues#queueSergmentOptions + } + + /** + * Generates a code sample for using {@link QueueServiceAsyncClient#listQueues(QueuesSegmentOptions)} + */ + public void listQueuesAsyncWithOverload() { + QueueServiceAsyncClient queueServiceAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueServiceAsyncClient.listQueues#queueSergmentOptions + queueServiceAsyncClient.listQueues(new QueuesSegmentOptions().prefix("azure")).subscribe( + queueItem -> System.out.printf("Queue %s exists in the account and has metadata %s", + queueItem.name(), queueItem.metadata()), + error -> System.err.print(error.toString()), + () -> System.out.println("Complete listing the queues!") + ); + // END: com.azure.storage.queue.queueServiceAsyncClient.listQueues#queueSergmentOptions + } + + /** + * Generates a code sample for using {@link QueueServiceClient#deleteQueue(String)} + */ + public void deleteQueue() { + QueueServiceClient queueServiceClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueServiceClient.deleteQueue#string + VoidResponse response = queueServiceClient.deleteQueue("myqueue"); + System.out.println("Complete deleting the queue with status code: " + response.statusCode()); + // END: com.azure.storage.queue.queueServiceClient.deleteQueue#string + } + + /** + * Generates a code sample for using {@link QueueServiceAsyncClient#deleteQueue(String)} + */ + public void deleteQueueAsync() { + QueueServiceAsyncClient queueServiceAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueServiceAsyncClient.deleteQueue#string + queueServiceAsyncClient.deleteQueue("myshare").subscribe( + response -> System.out.println("Deleting the queue completed with status code: " + response.statusCode()) + ); + // END: com.azure.storage.queue.queueServiceAsyncClient.deleteQueue#string + } + + /** + * Generates a code sample for using {@link QueueServiceClient#getProperties()} + */ + public void getProperties() { + QueueServiceClient queueServiceClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueServiceClient.getProperties + StorageServiceProperties properties = queueServiceClient.getProperties().value(); + System.out.printf("Hour metrics enabled: %b, Minute metrics enabled: %b", + properties.hourMetrics().enabled(), properties.minuteMetrics().enabled()); + // END: com.azure.storage.queue.queueServiceClient.getProperties + } + + /** + * Generates a code sample for using {@link QueueServiceAsyncClient#getProperties()} + */ + public void getPropertiesAsync() { + QueueServiceAsyncClient queueServiceAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueServiceAsyncClient.getProperties + queueServiceAsyncClient.getProperties() + .subscribe(response -> { + StorageServiceProperties properties = response.value(); + System.out.printf("Hour metrics enabled: %b, Minute metrics enabled: %b", + properties.hourMetrics().enabled(), properties.minuteMetrics().enabled()); + }); + // END: com.azure.storage.queue.queueServiceAsyncClient.getProperties + } + + /** + * Generates a code sample for using {@link QueueServiceClient#setProperties(StorageServiceProperties)} + */ + public void setProperties() { + QueueServiceClient queueServiceClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueServiceClient.setProperties#storageServiceProperties + StorageServiceProperties properties = queueServiceClient.getProperties().value(); + properties.cors(Collections.emptyList()); + + VoidResponse response = queueServiceClient.setProperties(properties); + System.out.printf("Setting Queue service properties completed with status code %d", response.statusCode()); + // END: com.azure.storage.queue.queueServiceClient.setProperties#storageServiceProperties + } + + /** + * Generates a code sample for using {@link QueueServiceAsyncClient#setProperties(StorageServiceProperties)} + */ + public void setPropertiesAsync() { + QueueServiceAsyncClient queueServiceAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueServiceAsyncClient.setProperties#storageServiceProperties + StorageServiceProperties properties = queueServiceAsyncClient.getProperties().block().value(); + queueServiceAsyncClient.setProperties(properties) + .subscribe(response -> System.out.printf("Setting Queue service properties completed with status code %d", + response.statusCode())); + // END: com.azure.storage.queue.queueServiceAsyncClient.setProperties#storageServiceProperties + } + + /** + * Generates a code sample for using {@link QueueServiceClient#setProperties(StorageServiceProperties)} with metrics enabled. + */ + public void setPropertiesEnableMetrics() { + QueueServiceClient queueServiceClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueServiceClient.setPropertiesEnableMetrics#storageServiceProperties + StorageServiceProperties properties = queueServiceClient.getProperties().value(); + properties.minuteMetrics().enabled(true); + properties.hourMetrics().enabled(true); + VoidResponse response = queueServiceClient.setProperties(properties); + System.out.printf("Setting Queue service properties completed with status code %d", response.statusCode()); + // END: com.azure.storage.queue.queueServiceClient.setPropertiesEnableMetrics#storageServiceProperties + } + + /** + * Generates a code sample for using {@link QueueServiceAsyncClient#setProperties(StorageServiceProperties)} with metrics enabled. + */ + public void setPropertiesAsyncEnableMetrics() { + QueueServiceAsyncClient queueServiceAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueServiceAsyncClient.setPropertiesEnableMetrics#storageServiceProperties + StorageServiceProperties properties = queueServiceAsyncClient.getProperties().block().value(); + properties.minuteMetrics().enabled(true); + properties.hourMetrics().enabled(true); + queueServiceAsyncClient.setProperties(properties) + .subscribe(response -> System.out.printf("Setting Queue service properties completed with status code %d", + response.statusCode())); + // END: com.azure.storage.queue.queueServiceAsyncClient.setPropertiesEnableMetrics#storageServiceProperties + } + + /** + * Generates a code sample for using {@link QueueServiceClient#getStatistics()} + */ + public void getStatistics() { + QueueServiceClient queueServiceClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueServiceClient.getStatistics + StorageServiceStats stats = queueServiceClient.getStatistics().value(); + System.out.printf("Geo replication status: %s, Last synced: %s", + stats.geoReplication().status(), stats.geoReplication().lastSyncTime()); + // END: com.azure.storage.queue.queueServiceClient.getStatistics + } + + /** + * Generates a code sample for using {@link QueueServiceAsyncClient#getStatistics()} + */ + public void getStatisticsAsync() { + QueueServiceAsyncClient queueServiceAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.queue.queueServiceAsyncClient.getStatistics + queueServiceAsyncClient.getStatistics() + .subscribe(response -> { + StorageServiceStats stats = response.value(); + System.out.printf("Geo replication status: %s, Last synced: %s", + stats.geoReplication().status(), stats.geoReplication().lastSyncTime()); + }); + // END: com.azure.storage.queue.queueServiceAsyncClient.getStatistics + } +} diff --git a/storage/client/queue/src/test/java/com/azure/storage/queue/QueueAsyncClientTests.java b/storage/client/queue/src/test/java/com/azure/storage/queue/QueueAsyncClientTests.java new file mode 100644 index 0000000000000..f658e2aff324b --- /dev/null +++ b/storage/client/queue/src/test/java/com/azure/storage/queue/QueueAsyncClientTests.java @@ -0,0 +1,695 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.storage.queue; + +import com.azure.core.http.HttpClient; +import com.azure.core.http.policy.HttpLogDetailLevel; +import com.azure.core.util.logging.ClientLogger; +import com.azure.storage.queue.models.AccessPolicy; +import com.azure.storage.queue.models.DequeuedMessage; +import com.azure.storage.queue.models.SignedIdentifier; +import com.azure.storage.queue.models.StorageErrorException; +import reactor.test.StepVerifier; + +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.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +public class QueueAsyncClientTests extends QueueClientTestsBase { + private final ClientLogger logger = new ClientLogger(QueueAsyncClientTests.class); + + private QueueAsyncClient client; + + @Override + protected void beforeTest() { + queueName = getQueueName(); + helper = new TestHelpers(); + + if (interceptorManager.isPlaybackMode()) { + client = helper.setupClient((connectionString, endpoint) -> new QueueClientBuilder() + .connectionString(connectionString) + .endpoint(endpoint) + .queueName(queueName) + .httpClient(interceptorManager.getPlaybackClient()) + .httpLogDetailLevel(HttpLogDetailLevel.BODY_AND_HEADERS) + .buildAsyncClient(), true, logger); + } else { + client = helper.setupClient((connectionString, endpoint) -> new QueueClientBuilder() + .connectionString(connectionString) + .endpoint(endpoint) + .queueName(queueName) + .httpClient(HttpClient.createDefault().wiretap(true)) + .httpLogDetailLevel(HttpLogDetailLevel.BODY_AND_HEADERS) + .addPolicy(interceptorManager.getRecordPolicy()) + .buildAsyncClient(), false, logger); + } + } + + @Override + protected void afterTest() { + try { + client.clearMessages().block(); + client.delete().block(); + } catch (StorageErrorException ex) { + // Queue already delete, that's what we wanted anyways. + } + } + + @Override + public void createWithSharedKey() { + + } + + @Override + public void createWithSASToken() { + // Need to find a way to get SAS tokens from the storage account + } + + @Override + public void createWithMetadata() { + Map metadata = new HashMap<>(); + metadata.put("metadata1", "value1"); + metadata.put("metadata2", "value2"); + + StepVerifier.create(client.create(metadata)) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(client.getProperties()) + .assertNext(response -> { + helper.assertResponseStatusCode(response, 200); + assertEquals(0, response.value().approximateMessagesCount()); + assertEquals(metadata, response.value().metadata()); + }) + .verifyComplete(); + } + + @Override + public void createTwiceSameMetadata() { + Map metadata = new HashMap<>(); + metadata.put("metadata1", "value1"); + metadata.put("metadata2", "value2"); + + StepVerifier.create(client.create(metadata)) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(client.create(metadata)) + .assertNext(response -> helper.assertResponseStatusCode(response, 204)) + .verifyComplete(); + } + + @Override + public void createTwiceDifferentMetadata() { + Map metadata = new HashMap<>(); + metadata.put("metadata1", "value1"); + metadata.put("metadata2", "value2"); + + StepVerifier.create(client.create()) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(client.create(metadata)) + .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 409)); + } + + @Override + public void deleteExisting() { + StepVerifier.create(client.create()) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(client.enqueueMessage("This queue will be deleted")) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(client.delete()) + .assertNext(response -> helper.assertResponseStatusCode(response, 204)) + .verifyComplete(); + + helper.sleepInRecordMode(Duration.ofSeconds(30)); + + StepVerifier.create(client.enqueueMessage("This should fail")) + .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 404)); + } + + @Override + public void deleteNonExistent() { + StepVerifier.create(client.delete()) + .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 404)); + } + + @Override + public void getProperties() { + Map metadata = new HashMap<>(); + metadata.put("metadata1", "value1"); + metadata.put("metadata2", "value2"); + + StepVerifier.create(client.create(metadata)) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(client.getProperties()) + .assertNext(response -> { + helper.assertResponseStatusCode(response, 200); + assertEquals(0, response.value().approximateMessagesCount()); + assertEquals(metadata, response.value().metadata()); + }) + .verifyComplete(); + } + + @Override + public void getPropertiesQueueDoesNotExist() { + StepVerifier.create(client.getProperties()) + .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 404)); + } + + @Override + public void setMetadata() { + Map metadata = new HashMap<>(); + metadata.put("metadata1", "value1"); + metadata.put("metadata2", "value2"); + + StepVerifier.create(client.create()) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(client.setMetadata(metadata)) + .assertNext(response -> helper.assertResponseStatusCode(response, 204)) + .verifyComplete(); + + StepVerifier.create(client.getProperties()) + .assertNext(response -> { + helper.assertResponseStatusCode(response, 200); + assertEquals(0, response.value().approximateMessagesCount()); + assertEquals(metadata, response.value().metadata()); + }) + .verifyComplete(); + } + + @Override + public void setMetadataQueueDoesNotExist() { + Map metadata = new HashMap<>(); + metadata.put("metadata1", "value1"); + metadata.put("metadata2", "value2"); + + StepVerifier.create(client.setMetadata(metadata)) + .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 404)); + } + + @Override + public void setInvalidMetadata() { + Map badMetadata = Collections.singletonMap("", "bad metadata"); + + StepVerifier.create(client.create()) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(client.setMetadata(badMetadata)) + .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 400)); + } + + @Override + public void deleteMetadata() { + Map metadata = new HashMap<>(); + metadata.put("metadata1", "value1"); + metadata.put("metadata2", "value2"); + + StepVerifier.create(client.create(metadata)) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(client.getProperties()) + .assertNext(response -> { + helper.assertResponseStatusCode(response, 200); + assertEquals(0, response.value().approximateMessagesCount()); + assertEquals(metadata, response.value().metadata()); + }) + .verifyComplete(); + + StepVerifier.create(client.setMetadata(null)) + .assertNext(response -> helper.assertResponseStatusCode(response, 204)) + .verifyComplete(); + + StepVerifier.create(client.getProperties()) + .assertNext(response -> { + helper.assertResponseStatusCode(response, 200); + assertEquals(Collections.EMPTY_MAP, response.value().metadata()); + }) + .verifyComplete(); + } + + @Override + public void getAccessPolicy() { + StepVerifier.create(client.create()) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(client.getAccessPolicy()) + .expectNextCount(0) + .verifyComplete(); + } + + @Override + public void getAccessPolicyQueueDoesNotExist() { + StepVerifier.create(client.getAccessPolicy()) + .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 404)); + } + + @Override + public void setAccessPolicy() { + StepVerifier.create(client.create()) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + AccessPolicy accessPolicy = new AccessPolicy() + .permission("raup") + .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("testpermission") + .accessPolicy(accessPolicy); + + StepVerifier.create(client.setAccessPolicy(Collections.singletonList(permission))) + .assertNext(response -> helper.assertResponseStatusCode(response, 204)) + .verifyComplete(); + + StepVerifier.create(client.getAccessPolicy()) + .assertNext(response -> helper.assertPermissionsAreEqual(permission, response)) + .verifyComplete(); + } + + @Override + public void setAccessPolicyQueueDoesNotExist() { + AccessPolicy accessPolicy = new AccessPolicy() + .permission("r") + .start(OffsetDateTime.now()) + .expiry(OffsetDateTime.now()); + + SignedIdentifier permission = new SignedIdentifier() + .id("test-permission") + .accessPolicy(accessPolicy); + + StepVerifier.create(client.setAccessPolicy(Collections.singletonList(permission))) + .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 400)); + } + + @Override + public void setInvalidAccessPolicy() { + AccessPolicy accessPolicy = 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("theidofthispermissionislongerthanwhatisallowedbytheserviceandshouldfail") + .accessPolicy(accessPolicy); + + StepVerifier.create(client.create()) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(client.setAccessPolicy(Collections.singletonList(permission))) + .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 400)); + } + + @Override + public void setTooManyAccessPolicies() { + AccessPolicy accessPolicy = 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)); + + List permissions = new ArrayList<>(); + for (int i = 0; i < 6; i++) { + permissions.add(new SignedIdentifier() + .id("policy" + i) + .accessPolicy(accessPolicy)); + } + + StepVerifier.create(client.create()) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(client.setAccessPolicy(permissions)) + .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 400)); + } + + @Override + public void enqueueMessage() { + StepVerifier.create(client.create()) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + String messageText = "test message"; + StepVerifier.create(client.enqueueMessage(messageText)) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(client.peekMessages()) + .assertNext(peekedMessage -> assertEquals(messageText, peekedMessage.messageText())) + .verifyComplete(); + } + + @Override + public void enqueueEmptyMessage() { + StepVerifier.create(client.create()) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + String messageText = ""; + StepVerifier.create(client.enqueueMessage(messageText)) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(client.peekMessages()) + .assertNext(peekedMessage -> assertNull(peekedMessage.messageText())) + .verifyComplete(); + } + + @Override + public void enqueueShortTimeToLiveMessage() { + StepVerifier.create(client.create()) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + String messageText = "test message"; + StepVerifier.create(client.enqueueMessage(messageText, Duration.ofSeconds(0), Duration.ofSeconds(2))) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(client.peekMessages().delaySubscription(Duration.ofSeconds(5))) + .expectNextCount(0) + .verifyComplete(); + } + + @Override + public void enqueueQueueDoesNotExist() { + StepVerifier.create(client.enqueueMessage("this should fail")) + .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 404)); + } + + @Override + public void dequeueMessage() { + StepVerifier.create(client.create()) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + String messageText = "test message"; + StepVerifier.create(client.enqueueMessage(messageText)) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(client.dequeueMessages()) + .assertNext(dequeuedMessage -> assertEquals(messageText, dequeuedMessage.messageText())) + .verifyComplete(); + } + + @Override + public void dequeueMultipleMessages() { + StepVerifier.create(client.create()) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + String messageText = "test message"; + String messageText2 = "test message 2"; + StepVerifier.create(client.enqueueMessage(messageText)) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(client.enqueueMessage(messageText2)) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(client.dequeueMessages(2)) + .assertNext(dequeuedMessage -> assertEquals(messageText, dequeuedMessage.messageText())) + .assertNext(dequeuedMessage -> assertEquals(messageText2, dequeuedMessage.messageText())) + .verifyComplete(); + } + + @Override + public void dequeueTooManyMessages() { + StepVerifier.create(client.create()) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(client.dequeueMessages(64)) + .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 400)); + } + + @Override + public void dequeueQueueDoesNotExist() { + StepVerifier.create(client.dequeueMessages()) + .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 404)); + } + + @Override + public void peekMessage() { + StepVerifier.create(client.create()) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + String messageText = "test message"; + StepVerifier.create(client.enqueueMessage(messageText)) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(client.peekMessages()) + .assertNext(peekedMessage -> assertEquals(messageText, peekedMessage.messageText())) + .verifyComplete(); + } + + @Override + public void peekMultipleMessages() { + StepVerifier.create(client.create()) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + String messageText = "test message"; + String messageText2 = "test message 2"; + StepVerifier.create(client.enqueueMessage(messageText)) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(client.enqueueMessage(messageText2)) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(client.peekMessages(2)) + .assertNext(peekedMessage -> assertEquals(messageText, peekedMessage.messageText())) + .assertNext(peekedMessage -> assertEquals(messageText2, peekedMessage.messageText())) + .verifyComplete(); + } + + @Override + public void peekTooManyMessages() { + StepVerifier.create(client.create()) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(client.peekMessages(64)) + .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 400)); + } + + @Override + public void peekQueueDoesNotExist() { + StepVerifier.create(client.peekMessages()) + .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 404)); + } + + @Override + public void clearMessages() { + StepVerifier.create(client.create()) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(client.enqueueMessage("test message")) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + StepVerifier.create(client.enqueueMessage("test message")) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + StepVerifier.create(client.enqueueMessage("test message")) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(client.getProperties()) + .assertNext(response -> { + helper.assertResponseStatusCode(response, 200); + assertEquals(3, response.value().approximateMessagesCount()); + }) + .verifyComplete(); + + StepVerifier.create(client.clearMessages()) + .assertNext(response -> helper.assertResponseStatusCode(response, 204)) + .verifyComplete(); + + StepVerifier.create(client.getProperties()) + .assertNext(response -> { + helper.assertResponseStatusCode(response, 200); + assertEquals(0, response.value().approximateMessagesCount()); + }) + .verifyComplete(); + } + + @Override + public void clearMessagesQueueDoesNotExist() { + StepVerifier.create(client.clearMessages()) + .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 404)); + } + + @Override + public void deleteMessage() { + StepVerifier.create(client.create()) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + String messageText = "test message"; + StepVerifier.create(client.enqueueMessage(messageText)) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + DequeuedMessage dequeuedMessage = client.dequeueMessages().blockFirst(); + assertEquals(messageText, dequeuedMessage.messageText()); + StepVerifier.create(client.deleteMessage(dequeuedMessage.messageId(), dequeuedMessage.popReceipt())) + .assertNext(response -> helper.assertResponseStatusCode(response, 204)) + .verifyComplete(); + + StepVerifier.create(client.getProperties()) + .assertNext(response -> { + helper.assertResponseStatusCode(response, 200); + assertEquals(0, response.value().approximateMessagesCount()); + }) + .verifyComplete(); + } + + @Override + public void deleteMessageInvalidMessageId() { + StepVerifier.create(client.create()) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + String messageText = "test message"; + StepVerifier.create(client.enqueueMessage(messageText)) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + DequeuedMessage dequeuedMessage = new DequeuedMessage(); + StepVerifier.create(client.dequeueMessages()) + .assertNext(response -> { + assertEquals(messageText, response.messageText()); + dequeuedMessage.popReceipt(response.popReceipt()).messageId(response.messageId()); + }) + .verifyComplete(); + + StepVerifier.create(client.deleteMessage(dequeuedMessage.messageId() + "random", dequeuedMessage.popReceipt())) + .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 404)); + } + + @Override + public void deleteMessageInvalidPopReceipt() { + StepVerifier.create(client.create()) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + String messageText = "test message"; + StepVerifier.create(client.enqueueMessage(messageText)) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + DequeuedMessage dequeuedMessage = new DequeuedMessage(); + StepVerifier.create(client.dequeueMessages()) + .assertNext(response -> { + assertEquals(messageText, response.messageText()); + dequeuedMessage.popReceipt(response.popReceipt()).messageId(response.messageId()); + }) + .verifyComplete(); + + StepVerifier.create(client.deleteMessage(dequeuedMessage.messageId(), dequeuedMessage.popReceipt() + "random")) + .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 400)); + } + + @Override + public void deleteMessageQueueDoesNotExist() { + StepVerifier.create(client.deleteMessage("invalid", "call")) + .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 404)); + } + + @Override + public void updateMessage() { + StepVerifier.create(client.create()) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + String messageText = "test message"; + StepVerifier.create(client.enqueueMessage(messageText)) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + DequeuedMessage dequeuedMessage = client.dequeueMessages().blockFirst(); + assertEquals(messageText, dequeuedMessage.messageText()); + + String updatedMessageText = "updated test message"; + StepVerifier.create(client.updateMessage(updatedMessageText, dequeuedMessage.messageId(), dequeuedMessage.popReceipt(), Duration.ofSeconds(1))) + .assertNext(response -> helper.assertResponseStatusCode(response, 204)) + .verifyComplete(); + + StepVerifier.create(client.peekMessages().delaySubscription(Duration.ofSeconds(2))) + .assertNext(response -> assertEquals(updatedMessageText, response.messageText())) + .verifyComplete(); + } + + @Override + public void updateMessageInvalidMessageId() { + StepVerifier.create(client.create()) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + String messageText = "test message"; + StepVerifier.create(client.enqueueMessage(messageText)) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + DequeuedMessage dequeuedMessage = client.dequeueMessages().blockFirst(); + assertEquals(messageText, dequeuedMessage.messageText()); + + String updatedMessageText = "updated test message"; + StepVerifier.create(client.updateMessage(updatedMessageText, dequeuedMessage.messageId() + "random", dequeuedMessage.popReceipt(), Duration.ofSeconds(1))) + .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 404)); + } + + @Override + public void updateMessageInvalidPopReceipt() { + StepVerifier.create(client.create()) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + String messageText = "test message"; + StepVerifier.create(client.enqueueMessage(messageText)) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + DequeuedMessage dequeuedMessage = client.dequeueMessages().blockFirst(); + assertEquals(messageText, dequeuedMessage.messageText()); + + String updatedMessageText = "updated test message"; + StepVerifier.create(client.updateMessage(updatedMessageText, dequeuedMessage.messageId(), dequeuedMessage.popReceipt() + "random", Duration.ofSeconds(1))) + .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 400)); + } + + @Override + public void updateMessageQueueDoesNotExist() { + StepVerifier.create(client.updateMessage("queue", "doesn't", "exist", Duration.ofSeconds(5))) + .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 400)); + } +} diff --git a/storage/client/queue/src/test/java/com/azure/storage/queue/QueueClientTests.java b/storage/client/queue/src/test/java/com/azure/storage/queue/QueueClientTests.java new file mode 100644 index 0000000000000..c0da15213d8c7 --- /dev/null +++ b/storage/client/queue/src/test/java/com/azure/storage/queue/QueueClientTests.java @@ -0,0 +1,654 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.storage.queue; + +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.queue.models.AccessPolicy; +import com.azure.storage.queue.models.DequeuedMessage; +import com.azure.storage.queue.models.PeekedMessage; +import com.azure.storage.queue.models.QueueProperties; +import com.azure.storage.queue.models.SignedIdentifier; +import com.azure.storage.queue.models.StorageErrorException; +import com.azure.storage.queue.models.UpdatedMessage; + +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.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; + +public class QueueClientTests extends QueueClientTestsBase { + private final ClientLogger logger = new ClientLogger(QueueClientTests.class); + + private QueueClient client; + + @Override + protected void beforeTest() { + queueName = getQueueName(); + helper = new TestHelpers(); + + if (interceptorManager.isPlaybackMode()) { + client = helper.setupClient((connectionString, endpoint) -> new QueueClientBuilder() + .connectionString(connectionString) + .endpoint(endpoint) + .queueName(queueName) + .httpClient(interceptorManager.getPlaybackClient()) + .httpLogDetailLevel(HttpLogDetailLevel.BODY_AND_HEADERS) + .buildClient(), true, logger); + } else { + client = helper.setupClient((connectionString, endpoint) -> new QueueClientBuilder() + .endpoint(endpoint) + .queueName(queueName) + .httpClient(HttpClient.createDefault().wiretap(true)) + .httpLogDetailLevel(HttpLogDetailLevel.BODY_AND_HEADERS) + .addPolicy(interceptorManager.getRecordPolicy()) + .buildClient(), false, logger); + } + } + + @Override + protected void afterTest() { + try { + client.clearMessages(); + client.delete(); + } catch (StorageErrorException ex) { + // Queue already delete, that's what we wanted anyways. + } + } + + @Override + public void createWithSharedKey() { + + } + + @Override + public void createWithSASToken() { + // Need to find a way to get SAS tokens from the storage account + } + + @Override + public void createWithMetadata() { + Map metadata = new HashMap<>(); + metadata.put("metadata1", "value1"); + metadata.put("metadata2", "value2"); + + helper.assertResponseStatusCode(client.create(metadata), 201); + + QueueProperties properties = client.getProperties().value(); + assertEquals(metadata, properties.metadata()); + } + + @Override + public void createTwiceSameMetadata() { + Map metadata = new HashMap<>(); + metadata.put("metadata1", "value1"); + metadata.put("metadata2", "value2"); + + helper.assertResponseStatusCode(client.create(metadata), 201); + helper.assertResponseStatusCode(client.create(metadata), 204); + } + + @Override + public void createTwiceDifferentMetadata() { + Map metadata = new HashMap<>(); + metadata.put("metadata1", "value1"); + metadata.put("metadata2", "value2"); + + helper.assertResponseStatusCode(client.create(), 201); + + try { + client.create(metadata); + fail("Creating a queue twice with different metadata values should throw an exception."); + } catch (Exception exception) { + helper.assertExceptionStatusCode(exception, 409); + } + } + + @Override + public void deleteExisting() { + helper.assertResponseStatusCode(client.create(), 201); + helper.assertResponseStatusCode(client.enqueueMessage("This queue will be deleted"), 201); + helper.assertResponseStatusCode(client.delete(), 204); + + helper.sleepInRecordMode(Duration.ofSeconds(30)); + + try { + client.enqueueMessage("This should fail"); + fail("Attempting to work with a queue that has been deleted should throw an exception."); + } catch (Exception exception) { + helper.assertExceptionStatusCode(exception, 404); + } + } + + @Override + public void deleteNonExistent() { + try { + client.delete(); + fail("Attempting to delete a queue that doesn't exist should throw an exception"); + } catch (Exception exception) { + helper.assertExceptionStatusCode(exception, 404); + } + } + + @Override + public void getProperties() { + Map metadata = new HashMap<>(); + metadata.put("metadata1", "value1"); + metadata.put("metadata2", "value2"); + + helper.assertResponseStatusCode(client.create(metadata), 201); + + Response response = client.getProperties(); + helper.assertResponseStatusCode(response, 200); + assertEquals(0, response.value().approximateMessagesCount()); + assertEquals(metadata, response.value().metadata()); + } + + @Override + public void getPropertiesQueueDoesNotExist() { + try { + client.getProperties(); + fail("Attempting to get properties of a queue that doesn't exist should throw an exception"); + } catch (Exception exception) { + helper.assertExceptionStatusCode(exception, 404); + } + } + + @Override + public void setMetadata() { + Map metadata = new HashMap<>(); + metadata.put("metadata1", "value1"); + metadata.put("metadata2", "value2"); + + helper.assertResponseStatusCode(client.create(), 201); + + helper.assertResponseStatusCode(client.setMetadata(metadata), 204); + + Response response = client.getProperties(); + helper.assertResponseStatusCode(response, 200); + assertEquals(0, response.value().approximateMessagesCount()); + assertEquals(metadata, response.value().metadata()); + } + + @Override + public void setMetadataQueueDoesNotExist() { + Map metadata = new HashMap<>(); + metadata.put("metadata1", "value1"); + metadata.put("metadata2", "value2"); + + try { + client.setMetadata(metadata); + fail("Attempting to set metadata on a queue that doesn't exist should throw an exception"); + } catch (Exception exception) { + helper.assertExceptionStatusCode(exception, 404); + } + } + + @Override + public void setInvalidMetadata() { + Map badMetadata = Collections.singletonMap("", "bad metadata"); + + helper.assertResponseStatusCode(client.create(), 201); + try { + client.setMetadata(badMetadata); + fail("Attempting to set invalid metadata on a queue that doesn't exist should throw an exception"); + } catch (Exception exception) { + helper.assertExceptionStatusCode(exception, 400); + } + } + + @Override + public void deleteMetadata() { + Map metadata = new HashMap<>(); + metadata.put("metadata1", "value1"); + metadata.put("metadata2", "value2"); + + helper.assertResponseStatusCode(client.create(metadata), 201); + + Response response = client.getProperties(); + helper.assertResponseStatusCode(response, 200); + assertEquals(0, response.value().approximateMessagesCount()); + assertEquals(metadata, response.value().metadata()); + + helper.assertResponseStatusCode(client.setMetadata(null), 204); + + response = client.getProperties(); + helper.assertResponseStatusCode(response, 200); + assertEquals(0, response.value().approximateMessagesCount()); + assertEquals(Collections.EMPTY_MAP, response.value().metadata()); + } + + @Override + public void getAccessPolicy() { + helper.assertResponseStatusCode(client.create(), 201); + + Iterable accessPolicies = client.getAccessPolicy(); + assertFalse(accessPolicies.iterator().hasNext()); + } + + @Override + public void getAccessPolicyQueueDoesNotExist() { + try { + client.getAccessPolicy().iterator().hasNext(); + fail("Attempting to get access policies on a queue that doesn't exist should throw an exception"); + } catch (Exception exception) { + helper.assertExceptionStatusCode(exception, 404); + } + } + + @Override + public void setAccessPolicy() { + helper.assertResponseStatusCode(client.create(), 201); + + AccessPolicy accessPolicy = new AccessPolicy() + .permission("raup") + .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("testpermission") + .accessPolicy(accessPolicy); + + helper.assertResponseStatusCode(client.setAccessPolicy(Collections.singletonList(permission)), 204); + + Iterator accessPolicies = client.getAccessPolicy().iterator(); + helper.assertPermissionsAreEqual(permission, accessPolicies.next()); + assertFalse(accessPolicies.hasNext()); + } + + @Override + public void setAccessPolicyQueueDoesNotExist() { + AccessPolicy accessPolicy = new AccessPolicy() + .permission("r") + .start(OffsetDateTime.now()) + .expiry(OffsetDateTime.now()); + + SignedIdentifier permission = new SignedIdentifier() + .id("test-permission") + .accessPolicy(accessPolicy); + + try { + client.setAccessPolicy(Collections.singletonList(permission)); + fail("Attempting to set access policies on a queue that doesn't exist should throw an exception"); + } catch (Exception exception) { + helper.assertExceptionStatusCode(exception, 400); + } + } + + @Override + public void setInvalidAccessPolicy() { + AccessPolicy accessPolicy = 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("theidofthispermissionislongerthanwhatisallowedbytheserviceandshouldfail") + .accessPolicy(accessPolicy); + + helper.assertResponseStatusCode(client.create(), 201); + + try { + client.setAccessPolicy(Collections.singletonList(permission)); + fail("Attempting to set invalid access policies on a queue that doesn't exist should throw an exception"); + } catch (Exception exception) { + helper.assertExceptionStatusCode(exception, 400); + } + } + + @Override + public void setTooManyAccessPolicies() { + List permissions = new ArrayList<>(); + + AccessPolicy accessPolicy = 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)); + + for (int i = 0; i < 6; i++) { + permissions.add(new SignedIdentifier() + .id("policy" + i) + .accessPolicy(accessPolicy)); + } + + helper.assertResponseStatusCode(client.create(), 201); + + try { + client.setAccessPolicy(permissions); + fail("Attempting to set more than five access policies on a queue that doesn't exist should throw an exception"); + } catch (Exception exception) { + helper.assertExceptionStatusCode(exception, 400); + } + } + + @Override + public void enqueueMessage() { + helper.assertResponseStatusCode(client.create(), 201); + + String messageText = "test message"; + helper.assertResponseStatusCode(client.enqueueMessage(messageText), 201); + + Iterator response = client.peekMessages().iterator(); + assertEquals(messageText, response.next().messageText()); + assertFalse(response.hasNext()); + } + + @Override + public void enqueueEmptyMessage() { + helper.assertResponseStatusCode(client.create(), 201); + + String messageText = ""; + helper.assertResponseStatusCode(client.enqueueMessage(messageText), 201); + + Iterator response = client.peekMessages().iterator(); + assertNull(response.next().messageText()); + assertFalse(response.hasNext()); + } + + @Override + public void enqueueShortTimeToLiveMessage() { + helper.assertResponseStatusCode(client.create(), 201); + + String messageText = "test message"; + helper.assertResponseStatusCode(client.enqueueMessage(messageText, Duration.ofSeconds(0), Duration.ofSeconds(2)), 201); + + helper.sleepInRecordMode(Duration.ofSeconds(5)); + Iterator response = client.peekMessages().iterator(); + assertFalse(response.hasNext()); + } + + @Override + public void enqueueQueueDoesNotExist() { + try { + client.enqueueMessage("This should fail"); + fail("Attempting to enqueue a message on a queue that doesn't exist should throw an exception"); + } catch (Exception exception) { + helper.assertExceptionStatusCode(exception, 404); + } + } + + @Override + public void dequeueMessage() { + helper.assertResponseStatusCode(client.create(), 201); + + String messageText = "test message"; + helper.assertResponseStatusCode(client.enqueueMessage(messageText), 201); + + Iterator response = client.dequeueMessages().iterator(); + assertEquals(messageText, response.next().messageText()); + assertFalse(response.hasNext()); + } + + @Override + public void dequeueMultipleMessages() { + helper.assertResponseStatusCode(client.create(), 201); + + String messageText = "test message"; + String messageText2 = "test message 2"; + helper.assertResponseStatusCode(client.enqueueMessage(messageText), 201); + helper.assertResponseStatusCode(client.enqueueMessage(messageText2), 201); + + Iterator response = client.dequeueMessages(2).iterator(); + assertEquals(messageText, response.next().messageText()); + assertEquals(messageText2, response.next().messageText()); + assertFalse(response.hasNext()); + } + + @Override + public void dequeueTooManyMessages() { + helper.assertResponseStatusCode(client.create(), 201); + + try { + client.dequeueMessages(64).iterator().hasNext(); + fail("Attempting to get more than 32 messages from a queue should throw an exception"); + } catch (Exception exception) { + helper.assertExceptionStatusCode(exception, 400); + } + } + + @Override + public void dequeueQueueDoesNotExist() { + try { + client.dequeueMessages().iterator().hasNext(); + fail("Attempting to get messages from a queue that doesn't exist should throw an exception"); + } catch (Exception exception) { + helper.assertExceptionStatusCode(exception, 404); + } + } + + @Override + public void peekMessage() { + helper.assertResponseStatusCode(client.create(), 201); + + String messageText = "test message"; + helper.assertResponseStatusCode(client.enqueueMessage(messageText), 201); + + Iterator response = client.peekMessages().iterator(); + assertEquals(messageText, response.next().messageText()); + assertFalse(response.hasNext()); + } + + @Override + public void peekMultipleMessages() { + helper.assertResponseStatusCode(client.create(), 201); + + String messageText = "test message"; + String messageText2 = "test message 2"; + helper.assertResponseStatusCode(client.enqueueMessage(messageText), 201); + helper.assertResponseStatusCode(client.enqueueMessage(messageText2), 201); + + Iterator response = client.peekMessages(2).iterator(); + assertEquals(messageText, response.next().messageText()); + assertEquals(messageText2, response.next().messageText()); + assertFalse(response.hasNext()); + } + + @Override + public void peekTooManyMessages() { + helper.assertResponseStatusCode(client.create(), 201); + + try { + client.peekMessages(64).iterator().hasNext(); + fail("Attempting to peek more than 32 messages from a queue should throw an exception"); + } catch (Exception exception) { + helper.assertExceptionStatusCode(exception, 400); + } + } + + @Override + public void peekQueueDoesNotExist() { + try { + client.peekMessages().iterator().hasNext(); + fail("Attempting to peek messages from a queue that doesn't exist should throw an exception"); + } catch (Exception exception) { + helper.assertExceptionStatusCode(exception, 404); + } + } + + @Override + public void clearMessages() { + helper.assertResponseStatusCode(client.create(), 201); + + for (int i = 0; i < 3; i++) { + helper.assertResponseStatusCode(client.enqueueMessage("test message"), 201); + } + + Response response = client.getProperties(); + helper.assertResponseStatusCode(response, 200); + assertEquals(3, response.value().approximateMessagesCount()); + + helper.assertResponseStatusCode(client.clearMessages(), 204); + + response = client.getProperties(); + helper.assertResponseStatusCode(response, 200); + assertEquals(0, response.value().approximateMessagesCount()); + } + + @Override + public void clearMessagesQueueDoesNotExist() { + try { + client.clearMessages(); + fail("Attempting to clear messages of a queue that doesn't exist should throw an exception"); + } catch (Exception exception) { + helper.assertExceptionStatusCode(exception, 404); + } + } + + @Override + public void deleteMessage() { + helper.assertResponseStatusCode(client.create(), 201); + + String messageText = "test message"; + helper.assertResponseStatusCode(client.enqueueMessage(messageText), 201); + + Iterator response = client.dequeueMessages().iterator(); + DequeuedMessage message = response.next(); + assertFalse(response.hasNext()); + assertEquals(messageText, message.messageText()); + + helper.assertResponseStatusCode(client.deleteMessage(message.messageId(), message.popReceipt()), 204); + + Response propertiesResponse = client.getProperties(); + helper.assertResponseStatusCode(propertiesResponse, 200); + assertEquals(0, propertiesResponse.value().approximateMessagesCount()); + } + + @Override + public void deleteMessageInvalidMessageId() { + helper.assertResponseStatusCode(client.create(), 201); + + String messageText = "test message"; + helper.assertResponseStatusCode(client.enqueueMessage(messageText), 201); + + Iterator response = client.dequeueMessages().iterator(); + DequeuedMessage message = response.next(); + assertFalse(response.hasNext()); + assertEquals(messageText, message.messageText()); + + try { + client.deleteMessage(message.messageId() + "random", message.popReceipt()); + fail("Attempting to delete a message with an invalid ID should throw an exception."); + } catch (Exception exception) { + helper.assertExceptionStatusCode(exception, 404); + } + } + + @Override + public void deleteMessageInvalidPopReceipt() { + helper.assertResponseStatusCode(client.create(), 201); + + String messageText = "test message"; + helper.assertResponseStatusCode(client.enqueueMessage(messageText), 201); + + Iterator response = client.dequeueMessages().iterator(); + DequeuedMessage message = response.next(); + assertFalse(response.hasNext()); + assertEquals(messageText, message.messageText()); + + try { + client.deleteMessage(message.messageId(), message.popReceipt() + "random"); + fail("Attempting to delete a message with an invalid popReceipt should throw an exception."); + } catch (Exception exception) { + helper.assertExceptionStatusCode(exception, 400); + } + } + + @Override + public void deleteMessageQueueDoesNotExist() { + try { + client.deleteMessage("invalid", "call"); + fail("Attempting to delete a message from a queue that doesn't exist should throw an exception."); + } catch (Exception exception) { + helper.assertExceptionStatusCode(exception, 404); + } + } + + @Override + public void updateMessage() { + helper.assertResponseStatusCode(client.create(), 201); + + String messageText = "test message"; + helper.assertResponseStatusCode(client.enqueueMessage(messageText), 201); + + Iterator response = client.dequeueMessages().iterator(); + DequeuedMessage message = response.next(); + assertEquals(messageText, message.messageText()); + assertFalse(response.hasNext()); + + String updatedMessageText = "updated test message"; + Response updatedMessageResponse = client.updateMessage(updatedMessageText, message.messageId(), message.popReceipt(), Duration.ofSeconds(1)); + helper.assertResponseStatusCode(updatedMessageResponse, 204); + + helper.sleepInRecordMode(Duration.ofSeconds(2)); + + Iterator peekedMessageIterator = client.peekMessages().iterator(); + PeekedMessage peekedMessage = peekedMessageIterator.next(); + assertEquals(updatedMessageText, peekedMessage.messageText()); + assertFalse(peekedMessageIterator.hasNext()); + } + + @Override + public void updateMessageInvalidMessageId() { + helper.assertResponseStatusCode(client.create(), 201); + + String messageText = "test message"; + helper.assertResponseStatusCode(client.enqueueMessage(messageText), 201); + + Iterator response = client.dequeueMessages().iterator(); + DequeuedMessage message = response.next(); + assertEquals(messageText, message.messageText()); + assertFalse(response.hasNext()); + + String updatedMessageText = "updated test message"; + try { + client.updateMessage(updatedMessageText, message.messageId() + "random", message.popReceipt(), Duration.ofSeconds(1)); + fail("Attempting to update a message with an invalid ID should throw an exception."); + } catch (Exception exception) { + helper.assertExceptionStatusCode(exception, 404); + } + } + + @Override + public void updateMessageInvalidPopReceipt() { + helper.assertResponseStatusCode(client.create(), 201); + + String messageText = "test message"; + helper.assertResponseStatusCode(client.enqueueMessage(messageText), 201); + + Iterator response = client.dequeueMessages().iterator(); + DequeuedMessage message = response.next(); + assertEquals(messageText, message.messageText()); + assertFalse(response.hasNext()); + + String updatedMessageText = "updated test message"; + try { + client.updateMessage(updatedMessageText, message.messageId(), message.popReceipt() + "random", Duration.ofSeconds(1)); + fail("Attempting to update a message with an invalid popReceipt should throw an exception."); + } catch (Exception exception) { + helper.assertExceptionStatusCode(exception, 400); + } + } + + @Override + public void updateMessageQueueDoesNotExist() { + try { + client.updateMessage("queue", "doesn't", "exist", Duration.ofSeconds(5)); + fail("Attempting to update a message on a queue that doesn't exist should throw an exception."); + } catch (Exception exception) { + helper.assertExceptionStatusCode(exception, 400); + } + } +} diff --git a/storage/client/queue/src/test/java/com/azure/storage/queue/QueueClientTestsBase.java b/storage/client/queue/src/test/java/com/azure/storage/queue/QueueClientTestsBase.java new file mode 100644 index 0000000000000..b83d9a1459bbc --- /dev/null +++ b/storage/client/queue/src/test/java/com/azure/storage/queue/QueueClientTestsBase.java @@ -0,0 +1,148 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.storage.queue; + +import com.azure.core.test.TestBase; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; + +public abstract class QueueClientTestsBase extends TestBase { + String queueName; + TestHelpers helper; + + @Rule + public TestName testName = new TestName(); + + @Override + public String testName() { + return testName.getMethodName(); + } + + String getQueueName() { + return testResourceNamer.randomName("queue", 16).toLowerCase(); + } + + @Test + public abstract void createWithSharedKey(); + + @Test + public abstract void createWithSASToken(); + + @Test + public abstract void createWithMetadata(); + + @Test + public abstract void createTwiceSameMetadata(); + + @Test + public abstract void createTwiceDifferentMetadata(); + + @Test + public abstract void deleteExisting(); + + @Test + public abstract void deleteNonExistent(); + + @Test + public abstract void getProperties(); + + @Test + public abstract void getPropertiesQueueDoesNotExist(); + + @Test + public abstract void setMetadata(); + + @Test + public abstract void setMetadataQueueDoesNotExist(); + + @Test + public abstract void setInvalidMetadata(); + + @Test + public abstract void deleteMetadata(); + + @Test + public abstract void getAccessPolicy(); + + @Test + public abstract void getAccessPolicyQueueDoesNotExist(); + + @Test + public abstract void setAccessPolicy(); + + @Test + public abstract void setAccessPolicyQueueDoesNotExist(); + + @Test + public abstract void setInvalidAccessPolicy(); + + @Test + public abstract void setTooManyAccessPolicies(); + + @Test + public abstract void enqueueMessage(); + + @Test + public abstract void enqueueEmptyMessage(); + + @Test + public abstract void enqueueShortTimeToLiveMessage(); + + @Test + public abstract void enqueueQueueDoesNotExist(); + + @Test + public abstract void dequeueMessage(); + + @Test + public abstract void dequeueMultipleMessages(); + + @Test + public abstract void dequeueTooManyMessages(); + + @Test + public abstract void dequeueQueueDoesNotExist(); + + @Test + public abstract void peekMessage(); + + @Test + public abstract void peekMultipleMessages(); + + @Test + public abstract void peekTooManyMessages(); + + @Test + public abstract void peekQueueDoesNotExist(); + + @Test + public abstract void clearMessages(); + + @Test + public abstract void clearMessagesQueueDoesNotExist(); + + @Test + public abstract void deleteMessage(); + + @Test + public abstract void deleteMessageInvalidMessageId(); + + @Test + public abstract void deleteMessageInvalidPopReceipt(); + + @Test + public abstract void deleteMessageQueueDoesNotExist(); + + @Test + public abstract void updateMessage(); + + @Test + public abstract void updateMessageInvalidMessageId(); + + @Test + public abstract void updateMessageInvalidPopReceipt(); + + @Test + public abstract void updateMessageQueueDoesNotExist(); +} diff --git a/storage/client/queue/src/test/java/com/azure/storage/queue/QueueServiceAsyncClientTests.java b/storage/client/queue/src/test/java/com/azure/storage/queue/QueueServiceAsyncClientTests.java new file mode 100644 index 0000000000000..8d0b89aa9be07 --- /dev/null +++ b/storage/client/queue/src/test/java/com/azure/storage/queue/QueueServiceAsyncClientTests.java @@ -0,0 +1,250 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.storage.queue; + +import com.azure.core.http.HttpClient; +import com.azure.core.http.policy.HttpLogDetailLevel; +import com.azure.core.util.logging.ClientLogger; +import com.azure.storage.queue.models.Logging; +import com.azure.storage.queue.models.Metrics; +import com.azure.storage.queue.models.QueueItem; +import com.azure.storage.queue.models.QueuesSegmentOptions; +import com.azure.storage.queue.models.RetentionPolicy; +import com.azure.storage.queue.models.StorageErrorException; +import com.azure.storage.queue.models.StorageServiceProperties; +import reactor.test.StepVerifier; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; + +import static org.junit.Assert.assertEquals; + +public class QueueServiceAsyncClientTests extends QueueServiceClientTestsBase { + private final ClientLogger logger = new ClientLogger(QueueServiceAsyncClientTests.class); + + private QueueServiceAsyncClient serviceClient; + + @Override + protected void beforeTest() { + queueName = getQueueName(); + helper = new TestHelpers(); + + if (interceptorManager.isPlaybackMode()) { + serviceClient = helper.setupClient((connectionString, endpoint) -> new QueueServiceClientBuilder() + .connectionString(connectionString) + .endpoint(endpoint) + .httpClient(interceptorManager.getPlaybackClient()) + .httpLogDetailLevel(HttpLogDetailLevel.BODY_AND_HEADERS) + .buildAsyncClient(), true, logger); + } else { + serviceClient = helper.setupClient((connectionString, endpoint) -> new QueueServiceClientBuilder() + .connectionString(connectionString) + .endpoint(endpoint) + .httpClient(HttpClient.createDefault().wiretap(true)) + .httpLogDetailLevel(HttpLogDetailLevel.BODY_AND_HEADERS) + .addPolicy(interceptorManager.getRecordPolicy()) + .buildAsyncClient(), false, logger); + } + } + + @Override + protected void afterTest() { + serviceClient.listQueues(new QueuesSegmentOptions().prefix(queueName)) + .collectList() + .block() + .forEach(queue -> { + QueueAsyncClient client = serviceClient.getQueueAsyncClient(queue.name()); + try { + client.clearMessages().then(client.delete()).block(); + } catch (StorageErrorException ex) { + // Queue already delete, that's what we wanted anyways. + } + }); + } + + @Override + public void getQueueDoesNotCreateAQueue() { + StepVerifier.create(serviceClient.getQueueAsyncClient(queueName).enqueueMessage("Expecting an exception")); + } + + @Override + public void createQueue() { + StepVerifier.create(serviceClient.createQueue(queueName).block().value().enqueueMessage("Testing service client creating a queue")) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + } + + @Override + public void createQueueWithMetadata() { + Map metadata = new HashMap<>(); + metadata.put("metadata1", "value1"); + metadata.put("metadata2", "value2"); + QueueAsyncClient client = serviceClient.createQueue(queueName, metadata).block().value(); + + StepVerifier.create(client.getProperties()) + .assertNext(response -> { + assertEquals(metadata, response.value().metadata()); + }) + .verifyComplete(); + } + + @Override + public void createQueueTwiceSameMetadata() { + final String messageText = "Testing service client creating the same queue twice does not modify the queue"; + Map metadata = new HashMap<>(); + metadata.put("metadata1", "value1"); + metadata.put("metadata2", "value2"); + + StepVerifier.create(serviceClient.createQueue(queueName, metadata).block().value().enqueueMessage(messageText)) + .assertNext(response -> helper.assertResponseStatusCode(response, 201)) + .verifyComplete(); + + StepVerifier.create(serviceClient.createQueue(queueName, metadata).block().value().peekMessages()) + .assertNext(response -> assertEquals(messageText, response.messageText())) + .verifyComplete(); + } + + @Override + public void createQueueTwiceDifferentMetadata() { + Map metadata = new HashMap<>(); + metadata.put("metadata1", "value1"); + metadata.put("metadata2", "value2"); + + try { + serviceClient.createQueue(queueName); + serviceClient.createQueue(queueName, metadata); + } catch (Exception exception) { + } + } + + @Override + public void deleteExistingQueue() { + QueueAsyncClient client = serviceClient.createQueue(queueName).block().value(); + serviceClient.deleteQueue(queueName).block(); + + StepVerifier.create(client.enqueueMessage("Expecting an exception")); + } + + @Override + public void deleteNonExistentQueue() { + try { + serviceClient.deleteQueue(queueName); + } catch (Exception exception) { + } + } + + @Override + public void listQueues() { + LinkedList testQueues = new LinkedList<>(); + for (int i = 0; i < 3; i++) { + QueueItem queue = new QueueItem().name(queueName + i); + testQueues.add(queue); + serviceClient.createQueue(queue.name(), queue.metadata()).block(); + } + + StepVerifier.create(serviceClient.listQueues(defaultSegmentOptions())) + .assertNext(result -> helper.assertQueuesAreEqual(testQueues.pop(), result)) + .assertNext(result -> helper.assertQueuesAreEqual(testQueues.pop(), result)) + .assertNext(result -> helper.assertQueuesAreEqual(testQueues.pop(), result)) + .verifyComplete(); + } + + @Override + public void listQueuesIncludeMetadata() { + Map metadata = new HashMap<>(); + metadata.put("metadata1", "value1"); + metadata.put("metadata2", "value2"); + + LinkedList testQueues = new LinkedList<>(); + for (int i = 0; i < 3; i++) { + QueueItem queue = new QueueItem().name(queueName + i); + if (i % 2 == 0) { + queue.metadata(metadata); + } + + testQueues.add(queue); + serviceClient.createQueue(queue.name(), queue.metadata()).block(); + } + + StepVerifier.create(serviceClient.listQueues(defaultSegmentOptions().includeMetadata(true))) + .assertNext(result -> helper.assertQueuesAreEqual(testQueues.pop(), result)) + .assertNext(result -> helper.assertQueuesAreEqual(testQueues.pop(), result)) + .assertNext(result -> helper.assertQueuesAreEqual(testQueues.pop(), result)) + .verifyComplete(); + } + + @Override + public void listQueuesWithPrefix() { + LinkedList testQueues = new LinkedList<>(); + for (int i = 0; i < 3; i++) { + QueueItem queue = new QueueItem(); + if (i % 2 == 0) { + queue.name(queueName + "prefix" + i); + testQueues.add(queue); + } else { + queue.name(queueName + i); + } + + serviceClient.createQueue(queue.name(), queue.metadata()).block(); + } + + StepVerifier.create(serviceClient.listQueues(defaultSegmentOptions().prefix(queueName + "prefix"))) + .assertNext(result -> helper.assertQueuesAreEqual(testQueues.pop(), result)) + .assertNext(result -> helper.assertQueuesAreEqual(testQueues.pop(), result)) + .verifyComplete(); + } + + @Override + public void listQueuesWithLimit() { + LinkedList testQueues = new LinkedList<>(); + for (int i = 0; i < 3; i++) { + QueueItem queue = new QueueItem().name(queueName + i); + testQueues.add(queue); + serviceClient.createQueue(queue.name(), queue.metadata()).block(); + } + + StepVerifier.create(serviceClient.listQueues(defaultSegmentOptions().maxResults(2))) + .verifyComplete(); + } + + @Override + public void setProperties() { + StorageServiceProperties originalProperties = serviceClient.getProperties().block().value(); + + RetentionPolicy retentionPolicy = new RetentionPolicy().enabled(true) + .days(3); + + Logging logging = new Logging().version("1.0") + .delete(true) + .write(true) + .retentionPolicy(retentionPolicy); + + Metrics metrics = new Metrics().enabled(true) + .includeAPIs(false) + .retentionPolicy(retentionPolicy) + .version("1.0"); + + StorageServiceProperties updatedProperties = new StorageServiceProperties().logging(logging) + .hourMetrics(metrics) + .minuteMetrics(metrics) + .cors(new ArrayList<>()); + + StepVerifier.create(serviceClient.setProperties(updatedProperties)) + .assertNext(response -> helper.assertResponseStatusCode(response, 202)) + .verifyComplete(); + + StepVerifier.create(serviceClient.getProperties()) + .assertNext(response -> helper.assertQueueServicePropertiesAreEqual(updatedProperties, response.value())) + .verifyComplete(); + + StepVerifier.create(serviceClient.setProperties(originalProperties)) + .assertNext(response -> helper.assertResponseStatusCode(response, 202)) + .verifyComplete(); + + StepVerifier.create(serviceClient.getProperties()) + .assertNext(response -> helper.assertQueueServicePropertiesAreEqual(originalProperties, response.value())) + .verifyComplete(); + } +} diff --git a/storage/client/queue/src/test/java/com/azure/storage/queue/QueueServiceClientTests.java b/storage/client/queue/src/test/java/com/azure/storage/queue/QueueServiceClientTests.java new file mode 100644 index 0000000000000..c6587872c6fb7 --- /dev/null +++ b/storage/client/queue/src/test/java/com/azure/storage/queue/QueueServiceClientTests.java @@ -0,0 +1,257 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.storage.queue; + +import com.azure.core.http.HttpClient; +import com.azure.core.http.policy.HttpLogDetailLevel; +import com.azure.core.http.rest.Response; +import com.azure.core.http.rest.VoidResponse; +import com.azure.core.util.logging.ClientLogger; +import com.azure.storage.queue.models.EnqueuedMessage; +import com.azure.storage.queue.models.Logging; +import com.azure.storage.queue.models.Metrics; +import com.azure.storage.queue.models.PeekedMessage; +import com.azure.storage.queue.models.QueueItem; +import com.azure.storage.queue.models.QueueProperties; +import com.azure.storage.queue.models.QueuesSegmentOptions; +import com.azure.storage.queue.models.RetentionPolicy; +import com.azure.storage.queue.models.StorageErrorException; +import com.azure.storage.queue.models.StorageServiceProperties; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +public class QueueServiceClientTests extends QueueServiceClientTestsBase { + private final ClientLogger logger = new ClientLogger(QueueServiceClientTests.class); + + private QueueServiceClient serviceClient; + + @Override + protected void beforeTest() { + queueName = getQueueName(); + helper = new TestHelpers(); + + if (interceptorManager.isPlaybackMode()) { + serviceClient = helper.setupClient((connectionString, endpoint) -> new QueueServiceClientBuilder() + .connectionString(connectionString) + .endpoint(endpoint) + .httpClient(interceptorManager.getPlaybackClient()) + .httpLogDetailLevel(HttpLogDetailLevel.BODY_AND_HEADERS) + .buildClient(), true, logger); + } else { + serviceClient = helper.setupClient((connectionString, endpoint) -> new QueueServiceClientBuilder() + .connectionString(connectionString) + .endpoint(endpoint) + .httpClient(HttpClient.createDefault().wiretap(true)) + .httpLogDetailLevel(HttpLogDetailLevel.BODY_AND_HEADERS) + .addPolicy(interceptorManager.getRecordPolicy()) + .buildClient(), false, logger); + } + } + + @Override + protected void afterTest() { + serviceClient.listQueues(new QueuesSegmentOptions().prefix(queueName)) + .forEach(queueToDelete -> { + try { + QueueClient client = serviceClient.getQueueClient(queueToDelete.name()); + client.clearMessages(); + client.delete(); + } catch (StorageErrorException ex) { + // Queue already delete, that's what we wanted anyways. + } + }); + } + + @Override + public void getQueueDoesNotCreateAQueue() { + try { + serviceClient.getQueueClient(queueName).enqueueMessage("Expecting an exception"); + fail("getQueueClient doesn't create a queue in Azure Storage."); + } catch (Exception exception) { + helper.assertExceptionStatusCode(exception, 404); + } + } + + @Override + public void createQueue() { + QueueClient client = serviceClient.createQueue(queueName).value(); + Response response = client.enqueueMessage("Testing service client creating a queue"); + helper.assertResponseStatusCode(response, 201); + } + + @Override + public void createQueueWithMetadata() { + Map metadata = new HashMap<>(); + metadata.put("metadata1", "value1"); + metadata.put("metadata2", "value2"); + QueueClient client = serviceClient.createQueue(queueName, metadata).value(); + + Response propertiesResponse = client.getProperties(); + helper.assertResponseStatusCode(propertiesResponse, 200); + assertEquals(metadata, propertiesResponse.value().metadata()); + } + + @Override + public void createQueueTwiceSameMetadata() { + final String messageText = "Testing service client creating the same queue twice does not modify the queue"; + Map metadata = new HashMap<>(); + metadata.put("metadata1", "value1"); + metadata.put("metadata2", "value2"); + + EnqueuedMessage enqueuedMessage = serviceClient.createQueue(queueName, metadata).value().enqueueMessage(messageText).value(); + assertNotNull(enqueuedMessage); + + PeekedMessage peekedMessage = serviceClient.createQueue(queueName, metadata).value().peekMessages().iterator().next(); + assertEquals(messageText, peekedMessage.messageText()); + } + + @Override + public void createQueueTwiceDifferentMetadata() { + Map metadata = new HashMap<>(); + metadata.put("metadata1", "value1"); + metadata.put("metadata2", "value2"); + + try { + serviceClient.createQueue(queueName); + serviceClient.createQueue(queueName, metadata); + fail("Creating a queue twice with different metadata should throw an exception."); + } catch (Exception exception) { + helper.assertExceptionStatusCode(exception, 409); + } + } + + @Override + public void deleteExistingQueue() { + QueueClient client = serviceClient.createQueue(queueName).value(); + serviceClient.deleteQueue(queueName); + + try { + client.enqueueMessage("Expecting an exception"); + fail("Attempting to enqueue a message on a client that has been delete should throw an exception."); + } catch (Exception exception) { + helper.assertExceptionStatusCode(exception, 404); + } + } + + @Override + public void deleteNonExistentQueue() { + try { + serviceClient.deleteQueue(queueName); + fail("Attempting to delete a queue that doesn't exist should throw an exception."); + } catch (Exception exception) { + helper.assertExceptionStatusCode(exception, 404); + } + } + + @Override + public void listQueues() { + LinkedList testQueues = new LinkedList<>(); + for (int i = 0; i < 3; i++) { + QueueItem queue = new QueueItem().name(queueName + i); + testQueues.add(queue); + serviceClient.createQueue(queue.name(), queue.metadata()); + } + + for (QueueItem queue : serviceClient.listQueues(defaultSegmentOptions())) { + helper.assertQueuesAreEqual(testQueues.pop(), queue); + } + } + + @Override + public void listQueuesIncludeMetadata() { + Map metadata = new HashMap<>(); + metadata.put("metadata1", "value1"); + metadata.put("metadata2", "value2"); + + LinkedList testQueues = new LinkedList<>(); + for (int i = 0; i < 3; i++) { + QueueItem queue = new QueueItem().name(queueName + i); + if (i % 2 == 0) { + queue.metadata(metadata); + } + + testQueues.add(queue); + serviceClient.createQueue(queue.name(), queue.metadata()); + } + + for (QueueItem queue : serviceClient.listQueues(defaultSegmentOptions().includeMetadata(true))) { + helper.assertQueuesAreEqual(testQueues.pop(), queue); + } + } + + @Override + public void listQueuesWithPrefix() { + LinkedList testQueues = new LinkedList<>(); + for (int i = 0; i < 3; i++) { + QueueItem queue = new QueueItem(); + if (i % 2 == 0) { + queue.name(queueName + "prefix" + i); + testQueues.add(queue); + } else { + queue.name(queueName + i); + } + + serviceClient.createQueue(queue.name(), queue.metadata()); + } + + for (QueueItem queue : serviceClient.listQueues(defaultSegmentOptions().prefix(queueName + "prefix"))) { + helper.assertQueuesAreEqual(testQueues.pop(), queue); + } + } + + @Override + public void listQueuesWithLimit() { + LinkedList testQueues = new LinkedList<>(); + for (int i = 0; i < 3; i++) { + QueueItem queue = new QueueItem().name(queueName + i); + testQueues.add(queue); + serviceClient.createQueue(queue.name(), queue.metadata()); + } + + for (QueueItem queue : serviceClient.listQueues(defaultSegmentOptions().maxResults(2))) { + helper.assertQueuesAreEqual(testQueues.pop(), queue); + } + } + + @Override + public void setProperties() { + StorageServiceProperties originalProperties = serviceClient.getProperties().value(); + + RetentionPolicy retentionPolicy = new RetentionPolicy().enabled(true) + .days(3); + + Logging logging = new Logging().version("1.0") + .delete(true) + .write(true) + .retentionPolicy(retentionPolicy); + + Metrics metrics = new Metrics().enabled(true) + .includeAPIs(false) + .retentionPolicy(retentionPolicy) + .version("1.0"); + + StorageServiceProperties updatedProperties = new StorageServiceProperties().logging(logging) + .hourMetrics(metrics) + .minuteMetrics(metrics) + .cors(new ArrayList<>()); + + VoidResponse setResponse = serviceClient.setProperties(updatedProperties); + helper.assertResponseStatusCode(setResponse, 202); + + Response getResponse = serviceClient.getProperties(); + helper.assertQueueServicePropertiesAreEqual(updatedProperties, getResponse.value()); + + setResponse = serviceClient.setProperties(originalProperties); + helper.assertResponseStatusCode(setResponse, 202); + + getResponse = serviceClient.getProperties(); + helper.assertQueueServicePropertiesAreEqual(originalProperties, getResponse.value()); + } +} diff --git a/storage/client/queue/src/test/java/com/azure/storage/queue/QueueServiceClientTestsBase.java b/storage/client/queue/src/test/java/com/azure/storage/queue/QueueServiceClientTestsBase.java new file mode 100644 index 0000000000000..3b86144d6f225 --- /dev/null +++ b/storage/client/queue/src/test/java/com/azure/storage/queue/QueueServiceClientTestsBase.java @@ -0,0 +1,67 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.storage.queue; + +import com.azure.core.test.TestBase; +import com.azure.storage.queue.models.QueuesSegmentOptions; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; + +public abstract class QueueServiceClientTestsBase extends TestBase { + String queueName; + TestHelpers helper; + + @Rule + public TestName testName = new TestName(); + + @Override + public String testName() { + return testName.getMethodName(); + } + + String getQueueName() { + return testResourceNamer.randomName("queue", 16).toLowerCase(); + } + + @Test + public abstract void getQueueDoesNotCreateAQueue(); + + @Test + public abstract void createQueue(); + + @Test + public abstract void createQueueWithMetadata(); + + @Test + public abstract void createQueueTwiceSameMetadata(); + + @Test + public abstract void createQueueTwiceDifferentMetadata(); + + @Test + public abstract void deleteExistingQueue(); + + @Test + public abstract void deleteNonExistentQueue(); + + @Test + public abstract void listQueues(); + + @Test + public abstract void listQueuesIncludeMetadata(); + + @Test + public abstract void listQueuesWithPrefix(); + + // TODO (alzimmer): This test is off for now until we determine how to handle paging with limited results + //@Test + public abstract void listQueuesWithLimit(); + + @Test + public abstract void setProperties(); + + QueuesSegmentOptions defaultSegmentOptions() { + return new QueuesSegmentOptions().prefix(queueName); + } +} diff --git a/storage/client/queue/src/test/java/com/azure/storage/queue/TestHelpers.java b/storage/client/queue/src/test/java/com/azure/storage/queue/TestHelpers.java new file mode 100644 index 0000000000000..bac3f552860fa --- /dev/null +++ b/storage/client/queue/src/test/java/com/azure/storage/queue/TestHelpers.java @@ -0,0 +1,161 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.storage.queue; + +import com.azure.core.http.rest.Response; +import com.azure.core.implementation.util.ImplUtils; +import com.azure.core.util.configuration.ConfigurationManager; +import com.azure.core.util.logging.ClientLogger; +import com.azure.storage.queue.models.CorsRule; +import com.azure.storage.queue.models.Logging; +import com.azure.storage.queue.models.Metrics; +import com.azure.storage.queue.models.QueueItem; +import com.azure.storage.queue.models.RetentionPolicy; +import com.azure.storage.queue.models.SignedIdentifier; +import com.azure.storage.queue.models.StorageErrorException; +import com.azure.storage.queue.models.StorageServiceProperties; + +import java.time.Duration; +import java.util.List; +import java.util.function.BiFunction; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +/** + * Contains helper methods for unit tests. + */ +class TestHelpers { + private final String azureStorageConnectionString = "AZURE_STORAGE_CONNECTION_STRING"; + private final String azureStorageQueueEndpoint = "AZURE_STORAGE_QUEUE_ENDPOINT"; + + T setupClient(BiFunction clientBuilder, boolean isPlaybackMode, ClientLogger logger) { + String connectionString = "DefaultEndpointsProtocol=https;AccountName=teststorage;AccountKey=atestaccountkey;EndpointSuffix=core.windows.net"; + String queueEndpoint = "https://teststorage.queue.core.windows.net/"; + + if (!isPlaybackMode) { + connectionString = ConfigurationManager.getConfiguration().get(azureStorageConnectionString); + queueEndpoint = ConfigurationManager.getConfiguration().get(azureStorageQueueEndpoint); + } + + if (ImplUtils.isNullOrEmpty(connectionString) && ImplUtils.isNullOrEmpty(queueEndpoint)) { + logger.asWarning().log("{} and {} must be set to build the testing client", azureStorageConnectionString, azureStorageQueueEndpoint); + fail(); + return null; + } + + return clientBuilder.apply(connectionString, queueEndpoint); + } + + void assertQueuesAreEqual(QueueItem expected, QueueItem actual) { + if (expected == null) { + assertNull(actual); + } else { + assertEquals(expected.name(), actual.name()); + + if (expected.metadata() != null && !ImplUtils.isNullOrEmpty(actual.metadata())) { + assertEquals(expected.metadata(), actual.metadata()); + } + } + } + + void assertQueueServicePropertiesAreEqual(StorageServiceProperties expected, StorageServiceProperties actual) { + if (expected == null) { + assertNull(actual); + } else { + assertMetricsAreEqual(expected.hourMetrics(), actual.hourMetrics()); + assertMetricsAreEqual(expected.minuteMetrics(), actual.minuteMetrics()); + assertLoggingAreEqual(expected.logging(), actual.logging()); + assertCorsAreEqual(expected.cors(), actual.cors()); + } + } + + private 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()); + } + } + + private void assertLoggingAreEqual(Logging expected, Logging actual) { + if (expected == null) { + assertNull(actual); + } else { + assertEquals(expected.read(), actual.read()); + assertEquals(expected.write(), actual.write()); + assertEquals(expected.delete(), actual.delete()); + assertEquals(expected.version(), actual.version()); + assertRetentionPoliciesAreEqual(expected.retentionPolicy(), actual.retentionPolicy()); + } + } + + private void assertRetentionPoliciesAreEqual(RetentionPolicy expected, RetentionPolicy actual) { + if (expected == null) { + assertNull(actual); + } else { + assertEquals(expected.days(), actual.days()); + assertEquals(expected.enabled(), actual.enabled()); + } + } + + private 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 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()); + } + } + + 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()); + } + + void assertResponseStatusCode(Response response, int expectedStatusCode) { + assertEquals(expectedStatusCode, response.statusCode()); + } + + void assertExceptionStatusCode(Throwable throwable, int expectedStatusCode) { + assertTrue(throwable instanceof StorageErrorException); + StorageErrorException storageErrorException = (StorageErrorException) throwable; + assertEquals(expectedStatusCode, storageErrorException.response().statusCode()); + } + + void sleepInRecordMode(Duration duration) { + String azureTestMode = ConfigurationManager.getConfiguration().get("AZURE_TEST_MODE"); + if ("RECORD".equalsIgnoreCase(azureTestMode)) { + sleep(duration); + } + } + + void sleep(Duration duration) { + try { + Thread.sleep(duration.toMillis()); + } catch (InterruptedException ex) { + // Ignore the error + } + } +} diff --git a/storage/client/queue/src/test/resources/session-records/clearMessages.json b/storage/client/queue/src/test/resources/session-records/clearMessages.json new file mode 100644 index 0000000000000..dab05b23fcfd5 --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/clearMessages.json @@ -0,0 +1,161 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue39460410", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd222863-4003-0028-6775-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:00 GMT" + } + }, { + "Method" : "POST", + "Uri" : "https://sima.queue.core.windows.net/queue39460410/messages?visibilitytimeout=0&messagettl=604800", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd2228a8-4003-0028-1b75-37b82d000000", + "Body" : "23ac390a-a15c-4036-b933-506b593e817aWed, 10 Jul 2019 23:18:01 GMTWed, 17 Jul 2019 23:18:01 GMTAgAAAAMAAAAAAAAAeGrWt3U31QE=Wed, 10 Jul 2019 23:18:01 GMT", + "Date" : "Wed, 10 Jul 2019 23:18:00 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "POST", + "Uri" : "https://sima.queue.core.windows.net/queue39460410/messages?visibilitytimeout=0&messagettl=604800", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd2228d0-4003-0028-3a75-37b82d000000", + "Body" : "0820c842-8ea6-466f-801e-8fdb0240f573Wed, 10 Jul 2019 23:18:01 GMTWed, 17 Jul 2019 23:18:01 GMTAgAAAAMAAAAAAAAARoLet3U31QE=Wed, 10 Jul 2019 23:18:01 GMT", + "Date" : "Wed, 10 Jul 2019 23:18:00 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "POST", + "Uri" : "https://sima.queue.core.windows.net/queue39460410/messages?visibilitytimeout=0&messagettl=604800", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd2228f8-4003-0028-5975-37b82d000000", + "Body" : "1a2b254b-4f28-4dba-8a56-5947173e08faWed, 10 Jul 2019 23:18:01 GMTWed, 17 Jul 2019 23:18:01 GMTAgAAAAMAAAAAAAAA5kvmt3U31QE=Wed, 10 Jul 2019 23:18:01 GMT", + "Date" : "Wed, 10 Jul 2019 23:18:00 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net/queue39460410?comp=metadata", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "Content-Length" : "0", + "x-ms-approximate-messages-count" : "3", + "StatusCode" : "200", + "x-ms-request-id" : "dd222917-4003-0028-7175-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:00 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue39460410/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd22292f-4003-0028-0775-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:00 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net/queue39460410?comp=metadata", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "Content-Length" : "0", + "x-ms-approximate-messages-count" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "dd222940-4003-0028-1575-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:01 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue39460410/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd22295c-4003-0028-2975-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:01 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue39460410", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd222973-4003-0028-3e75-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:01 GMT" + } + } ], + "variables" : [ "queue39460410" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/clearMessagesQueueDoesNotExist.json b/storage/client/queue/src/test/resources/session-records/clearMessagesQueueDoesNotExist.json new file mode 100644 index 0000000000000..9fb11f03c6960 --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/clearMessagesQueueDoesNotExist.json @@ -0,0 +1,42 @@ +{ + "networkCallRecords" : [ { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue0499487b/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "QueueNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "dd223222-4003-0028-3175-37b82d000000", + "Body" : "QueueNotFoundThe specified queue does not exist.\nRequestId:dd223222-4003-0028-3175-37b82d000000\nTime:2019-07-10T23:18:05.7976908Z", + "Date" : "Wed, 10 Jul 2019 23:18:05 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue0499487b/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "QueueNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "dd223243-4003-0028-4e75-37b82d000000", + "Body" : "QueueNotFoundThe specified queue does not exist.\nRequestId:dd223243-4003-0028-4e75-37b82d000000\nTime:2019-07-10T23:18:05.8547315Z", + "Date" : "Wed, 10 Jul 2019 23:18:05 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "queue0499487b" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/createQueue.json b/storage/client/queue/src/test/resources/session-records/createQueue.json new file mode 100644 index 0000000000000..51d4b6d64f5b5 --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/createQueue.json @@ -0,0 +1,90 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue09262a67", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "0d29065a-6003-009e-2f76-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:47 GMT" + } + }, { + "Method" : "POST", + "Uri" : "https://sima.queue.core.windows.net/queue09262a67/messages?visibilitytimeout=0&messagettl=604800", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "0d290667-6003-009e-3b76-37b6d5000000", + "Body" : "94fd0809-1708-49c0-91ea-d4cf2141af7fWed, 10 Jul 2019 23:24:47 GMTWed, 17 Jul 2019 23:24:47 GMTAgAAAAMAAAAAAAAAREDwqXY31QE=Wed, 10 Jul 2019 23:24:47 GMT", + "Date" : "Wed, 10 Jul 2019 23:24:47 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net?prefix=queue09262a67&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "0d29067f-6003-009e-5376-37b6d5000000", + "Body" : "queue09262a67queue09262a67", + "Date" : "Wed, 10 Jul 2019 23:24:47 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue09262a67/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "0d290694-6003-009e-6676-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:47 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue09262a67", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "0d2906a1-6003-009e-7376-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:47 GMT" + } + } ], + "variables" : [ "queue09262a67" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/createQueueTwiceDifferentMetadata.json b/storage/client/queue/src/test/resources/session-records/createQueueTwiceDifferentMetadata.json new file mode 100644 index 0000000000000..e7297afd23b18 --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/createQueueTwiceDifferentMetadata.json @@ -0,0 +1,90 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue2172697c", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "0d290a57-6003-009e-6676-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:49 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue2172697c", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "QueueAlreadyExists", + "retry-after" : "0", + "Content-Length" : "222", + "StatusCode" : "409", + "x-ms-request-id" : "0d290a73-6003-009e-7e76-37b6d5000000", + "Body" : "QueueAlreadyExistsThe specified queue already exists.\nRequestId:0d290a73-6003-009e-7e76-37b6d5000000\nTime:2019-07-10T23:24:49.9481623Z", + "Date" : "Wed, 10 Jul 2019 23:24:49 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net?prefix=queue2172697c&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "0d290a84-6003-009e-0f76-37b6d5000000", + "Body" : "queue2172697cqueue2172697c", + "Date" : "Wed, 10 Jul 2019 23:24:49 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue2172697c/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "0d290a9d-6003-009e-2776-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:50 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue2172697c", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "0d290aa4-6003-009e-2d76-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:50 GMT" + } + } ], + "variables" : [ "queue2172697c" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/createQueueTwiceSameMetadata.json b/storage/client/queue/src/test/resources/session-records/createQueueTwiceSameMetadata.json new file mode 100644 index 0000000000000..5f637cb224b88 --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/createQueueTwiceSameMetadata.json @@ -0,0 +1,125 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue3315117d", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "0d29094b-6003-009e-0a76-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:49 GMT" + } + }, { + "Method" : "POST", + "Uri" : "https://sima.queue.core.windows.net/queue3315117d/messages?visibilitytimeout=0&messagettl=604800", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "0d29096a-6003-009e-2176-37b6d5000000", + "Body" : "e59cbb06-dc9a-4fd8-89c9-a62bec05127eWed, 10 Jul 2019 23:24:49 GMTWed, 17 Jul 2019 23:24:49 GMTAgAAAAMAAAAAAAAAh80Wq3Y31QE=Wed, 10 Jul 2019 23:24:49 GMT", + "Date" : "Wed, 10 Jul 2019 23:24:49 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue3315117d", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "0d290979-6003-009e-2d76-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:49 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net/queue3315117d/messages?peekonly=true", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "0d29099f-6003-009e-4b76-37b6d5000000", + "Body" : "e59cbb06-dc9a-4fd8-89c9-a62bec05127eWed, 10 Jul 2019 23:24:49 GMTWed, 17 Jul 2019 23:24:49 GMT0Testing service client creating the same queue twice does not modify the queue", + "Date" : "Wed, 10 Jul 2019 23:24:49 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net?prefix=queue3315117d&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "0d2909d4-6003-009e-7a76-37b6d5000000", + "Body" : "queue3315117dqueue3315117d", + "Date" : "Wed, 10 Jul 2019 23:24:49 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue3315117d/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "0d2909eb-6003-009e-0e76-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:49 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue3315117d", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "0d2909f9-6003-009e-1b76-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:49 GMT" + } + } ], + "variables" : [ "queue3315117d" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/createQueueWithMetadata.json b/storage/client/queue/src/test/resources/session-records/createQueueWithMetadata.json new file mode 100644 index 0000000000000..3c8381cb87770 --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/createQueueWithMetadata.json @@ -0,0 +1,91 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue2741227a", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "0d290770-6003-009e-1d76-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:48 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net/queue2741227a?comp=metadata", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "Content-Length" : "0", + "x-ms-approximate-messages-count" : "0", + "x-ms-meta-metadata1" : "value1", + "StatusCode" : "200", + "x-ms-request-id" : "0d290788-6003-009e-3176-37b6d5000000", + "x-ms-meta-metadata2" : "value2", + "Date" : "Wed, 10 Jul 2019 23:24:48 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net?prefix=queue2741227a&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "0d2907ab-6003-009e-4e76-37b6d5000000", + "Body" : "queue2741227aqueue2741227a", + "Date" : "Wed, 10 Jul 2019 23:24:48 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue2741227a/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "0d2907b9-6003-009e-5976-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:48 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue2741227a", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "0d2907c4-6003-009e-6276-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:48 GMT" + } + } ], + "variables" : [ "queue2741227a" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/createTwiceDifferentMetadata.json b/storage/client/queue/src/test/resources/session-records/createTwiceDifferentMetadata.json new file mode 100644 index 0000000000000..2c1103e32db9c --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/createTwiceDifferentMetadata.json @@ -0,0 +1,71 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue0432116e", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd226070-4003-0028-4675-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:37 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue0432116e", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "QueueAlreadyExists", + "retry-after" : "0", + "Content-Length" : "222", + "StatusCode" : "409", + "x-ms-request-id" : "dd22608d-4003-0028-5f75-37b82d000000", + "Body" : "QueueAlreadyExistsThe specified queue already exists.\nRequestId:dd22608d-4003-0028-5f75-37b82d000000\nTime:2019-07-10T23:18:38.0176580Z", + "Date" : "Wed, 10 Jul 2019 23:18:37 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue0432116e/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd22609f-4003-0028-7175-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:37 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue0432116e", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd2260a4-4003-0028-7675-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:37 GMT" + } + } ], + "variables" : [ "queue0432116e" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/createTwiceSameMetadata.json b/storage/client/queue/src/test/resources/session-records/createTwiceSameMetadata.json new file mode 100644 index 0000000000000..67e8f6692f9ce --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/createTwiceSameMetadata.json @@ -0,0 +1,68 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue1490420b", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd225ee9-4003-0028-6675-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:36 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue1490420b", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd225f04-4003-0028-7875-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:36 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue1490420b/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd225f21-4003-0028-1175-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:36 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue1490420b", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd225f32-4003-0028-2175-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:36 GMT" + } + } ], + "variables" : [ "queue1490420b" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/createWithMetadata.json b/storage/client/queue/src/test/resources/session-records/createWithMetadata.json new file mode 100644 index 0000000000000..e81225ed944ad --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/createWithMetadata.json @@ -0,0 +1,72 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue98908a15", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd2231c8-4003-0028-6375-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:05 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net/queue98908a15?comp=metadata", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "Content-Length" : "0", + "x-ms-approximate-messages-count" : "0", + "x-ms-meta-metadata1" : "value1", + "StatusCode" : "200", + "x-ms-request-id" : "dd2231df-4003-0028-7475-37b82d000000", + "x-ms-meta-metadata2" : "value2", + "Date" : "Wed, 10 Jul 2019 23:18:05 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue98908a15/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd2231f6-4003-0028-0975-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:05 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue98908a15", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd223209-4003-0028-1b75-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:05 GMT" + } + } ], + "variables" : [ "queue98908a15" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/createWithSASToken.json b/storage/client/queue/src/test/resources/session-records/createWithSASToken.json new file mode 100644 index 0000000000000..b0f0da481c199 --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/createWithSASToken.json @@ -0,0 +1,23 @@ +{ + "networkCallRecords" : [ { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue99626420/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "QueueNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "dd222843-4003-0028-5275-37b82d000000", + "Body" : "QueueNotFoundThe specified queue does not exist.\nRequestId:dd222843-4003-0028-5275-37b82d000000\nTime:2019-07-10T23:18:01.0102891Z", + "Date" : "Wed, 10 Jul 2019 23:18:00 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "queue99626420" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/createWithSharedKey.json b/storage/client/queue/src/test/resources/session-records/createWithSharedKey.json new file mode 100644 index 0000000000000..45ad59b25dadb --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/createWithSharedKey.json @@ -0,0 +1,23 @@ +{ + "networkCallRecords" : [ { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue46849fbc/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "QueueNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "dd226200-4003-0028-1275-37b82d000000", + "Body" : "QueueNotFoundThe specified queue does not exist.\nRequestId:dd226200-4003-0028-1275-37b82d000000\nTime:2019-07-10T23:18:39.1594759Z", + "Date" : "Wed, 10 Jul 2019 23:18:38 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "queue46849fbc" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/deleteExisting.json b/storage/client/queue/src/test/resources/session-records/deleteExisting.json new file mode 100644 index 0000000000000..ffaa890d17294 --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/deleteExisting.json @@ -0,0 +1,94 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue69325b7f", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd223362-4003-0028-4f75-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:05 GMT" + } + }, { + "Method" : "POST", + "Uri" : "https://sima.queue.core.windows.net/queue69325b7f/messages?visibilitytimeout=0&messagettl=604800", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd223387-4003-0028-7075-37b82d000000", + "Body" : "23c03c48-1eb9-48c9-aded-b6c6adb39e9eWed, 10 Jul 2019 23:18:06 GMTWed, 17 Jul 2019 23:18:06 GMTAgAAAAMAAAAAAAAA1NHmunU31QE=Wed, 10 Jul 2019 23:18:06 GMT", + "Date" : "Wed, 10 Jul 2019 23:18:05 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue69325b7f", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd223398-4003-0028-0175-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:05 GMT" + } + }, { + "Method" : "POST", + "Uri" : "https://sima.queue.core.windows.net/queue69325b7f/messages?visibilitytimeout=0&messagettl=604800", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "QueueNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "dd225eb4-4003-0028-3c75-37b82d000000", + "Body" : "QueueNotFoundThe specified queue does not exist.\nRequestId:dd225eb4-4003-0028-3c75-37b82d000000\nTime:2019-07-10T23:18:36.4715552Z", + "Date" : "Wed, 10 Jul 2019 23:18:35 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue69325b7f/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "QueueNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "dd225ecd-4003-0028-5175-37b82d000000", + "Body" : "QueueNotFoundThe specified queue does not exist.\nRequestId:dd225ecd-4003-0028-5175-37b82d000000\nTime:2019-07-10T23:18:36.5175891Z", + "Date" : "Wed, 10 Jul 2019 23:18:36 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "queue69325b7f" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/deleteExistingQueue.json b/storage/client/queue/src/test/resources/session-records/deleteExistingQueue.json new file mode 100644 index 0000000000000..414ed34da046c --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/deleteExistingQueue.json @@ -0,0 +1,75 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue15727eac", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "0d290577-6003-009e-6976-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:46 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue15727eac", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "0d2905e7-6003-009e-4776-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:46 GMT" + } + }, { + "Method" : "POST", + "Uri" : "https://sima.queue.core.windows.net/queue15727eac/messages?visibilitytimeout=0&messagettl=604800", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "QueueNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "0d290618-6003-009e-7176-37b6d5000000", + "Body" : "QueueNotFoundThe specified queue does not exist.\nRequestId:0d290618-6003-009e-7176-37b6d5000000\nTime:2019-07-10T23:24:47.1091308Z", + "Date" : "Wed, 10 Jul 2019 23:24:47 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net?prefix=queue15727eac&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "0d290643-6003-009e-1b76-37b6d5000000", + "Body" : "queue15727eac", + "Date" : "Wed, 10 Jul 2019 23:24:47 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "queue15727eac" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/deleteMessage.json b/storage/client/queue/src/test/resources/session-records/deleteMessage.json new file mode 100644 index 0000000000000..4682bf4a1a131 --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/deleteMessage.json @@ -0,0 +1,124 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue1154048f", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd226162-4003-0028-1e75-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:38 GMT" + } + }, { + "Method" : "POST", + "Uri" : "https://sima.queue.core.windows.net/queue1154048f/messages?visibilitytimeout=0&messagettl=604800", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd226172-4003-0028-2a75-37b82d000000", + "Body" : "5d20d094-2ec7-4544-9ad1-86fc3aa14140Wed, 10 Jul 2019 23:18:38 GMTWed, 17 Jul 2019 23:18:38 GMTAgAAAAMAAAAAAAAAskA9znU31QE=Wed, 10 Jul 2019 23:18:38 GMT", + "Date" : "Wed, 10 Jul 2019 23:18:38 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net/queue1154048f/messages?numofmessages=1&visibilitytimeout=30", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "dd226183-4003-0028-3675-37b82d000000", + "Body" : "5d20d094-2ec7-4544-9ad1-86fc3aa14140Wed, 10 Jul 2019 23:18:38 GMTWed, 17 Jul 2019 23:18:38 GMTAgAAAAMAAAAAAAAAOIYm4HU31QE=Wed, 10 Jul 2019 23:19:08 GMT1test message", + "Date" : "Wed, 10 Jul 2019 23:18:38 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue1154048f/messages/5d20d094-2ec7-4544-9ad1-86fc3aa14140?popreceipt=AgAAAAMAAAAAAAAAOIYm4HU31QE%3d", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd226190-4003-0028-3f75-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:38 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net/queue1154048f?comp=metadata", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "Content-Length" : "0", + "x-ms-approximate-messages-count" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "dd2261a5-4003-0028-4e75-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:38 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue1154048f/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd2261ba-4003-0028-5e75-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:38 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue1154048f", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd2261ce-4003-0028-6c75-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:38 GMT" + } + } ], + "variables" : [ "queue1154048f" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/deleteMessageInvalidMessageId.json b/storage/client/queue/src/test/resources/session-records/deleteMessageInvalidMessageId.json new file mode 100644 index 0000000000000..4eccb534a46f3 --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/deleteMessageInvalidMessageId.json @@ -0,0 +1,109 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue96938aad", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd221ea5-4003-0028-1075-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:17:53 GMT" + } + }, { + "Method" : "POST", + "Uri" : "https://sima.queue.core.windows.net/queue96938aad/messages?visibilitytimeout=0&messagettl=604800", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd221eb9-4003-0028-2375-37b82d000000", + "Body" : "17aa480c-b8aa-47ce-9fdb-753a00853819Wed, 10 Jul 2019 23:17:54 GMTWed, 17 Jul 2019 23:17:54 GMTAgAAAAMAAAAAAAAALPXXs3U31QE=Wed, 10 Jul 2019 23:17:54 GMT", + "Date" : "Wed, 10 Jul 2019 23:17:54 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net/queue96938aad/messages?numofmessages=1&visibilitytimeout=30", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "dd221ecb-4003-0028-3575-37b82d000000", + "Body" : "17aa480c-b8aa-47ce-9fdb-753a00853819Wed, 10 Jul 2019 23:17:54 GMTWed, 17 Jul 2019 23:17:54 GMTAgAAAAMAAAAAAAAA4IjBxXU31QE=Wed, 10 Jul 2019 23:18:24 GMT1test message", + "Date" : "Wed, 10 Jul 2019 23:17:54 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue96938aad/messages/17aa480c-b8aa-47ce-9fdb-753a00853819random?popreceipt=AgAAAAMAAAAAAAAA4IjBxXU31QE%3d", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "MessageNotFound", + "retry-after" : "0", + "Content-Length" : "221", + "StatusCode" : "404", + "x-ms-request-id" : "dd221ee5-4003-0028-4d75-37b82d000000", + "Body" : "MessageNotFoundThe specified message does not exist.\nRequestId:dd221ee5-4003-0028-4d75-37b82d000000\nTime:2019-07-10T23:17:54.6327585Z", + "Date" : "Wed, 10 Jul 2019 23:17:54 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue96938aad/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd221ef8-4003-0028-5f75-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:17:54 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue96938aad", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd221f17-4003-0028-7c75-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:17:54 GMT" + } + } ], + "variables" : [ "queue96938aad" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/deleteMessageInvalidPopReceipt.json b/storage/client/queue/src/test/resources/session-records/deleteMessageInvalidPopReceipt.json new file mode 100644 index 0000000000000..01154b0b743de --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/deleteMessageInvalidPopReceipt.json @@ -0,0 +1,109 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue67327535", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd221e11-4003-0028-0575-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:17:53 GMT" + } + }, { + "Method" : "POST", + "Uri" : "https://sima.queue.core.windows.net/queue67327535/messages?visibilitytimeout=0&messagettl=604800", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd221e1c-4003-0028-0f75-37b82d000000", + "Body" : "a848cec9-d421-43a6-ac39-6a941d76d21bWed, 10 Jul 2019 23:17:54 GMTWed, 17 Jul 2019 23:17:54 GMTAgAAAAMAAAAAAAAAJDmgs3U31QE=Wed, 10 Jul 2019 23:17:54 GMT", + "Date" : "Wed, 10 Jul 2019 23:17:53 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net/queue67327535/messages?numofmessages=1&visibilitytimeout=30", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "dd221e2b-4003-0028-1e75-37b82d000000", + "Body" : "a848cec9-d421-43a6-ac39-6a941d76d21bWed, 10 Jul 2019 23:17:54 GMTWed, 17 Jul 2019 23:17:54 GMTAgAAAAMAAAAAAAAANWmKxXU31QE=Wed, 10 Jul 2019 23:18:24 GMT1test message", + "Date" : "Wed, 10 Jul 2019 23:17:53 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue67327535/messages/a848cec9-d421-43a6-ac39-6a941d76d21b?popreceipt=AgAAAAMAAAAAAAAANWmKxXU31QE%3drandom", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "InvalidQueryParameterValue", + "retry-after" : "0", + "Content-Length" : "444", + "StatusCode" : "400", + "x-ms-request-id" : "dd221e4c-4003-0028-3c75-37b82d000000", + "Body" : "InvalidQueryParameterValueValue for one of the query parameters specified in the request URI is invalid.\nRequestId:dd221e4c-4003-0028-3c75-37b82d000000\nTime:2019-07-10T23:17:54.2735030ZpopreceiptAgAAAAMAAAAAAAAANWmKxXU31QE=randomInvalid pop receipt format", + "Date" : "Wed, 10 Jul 2019 23:17:53 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue67327535/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd221e6a-4003-0028-5575-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:17:53 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue67327535", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd221e7b-4003-0028-6675-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:17:53 GMT" + } + } ], + "variables" : [ "queue67327535" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/deleteMessageQueueDoesNotExist.json b/storage/client/queue/src/test/resources/session-records/deleteMessageQueueDoesNotExist.json new file mode 100644 index 0000000000000..c03dedb5c4887 --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/deleteMessageQueueDoesNotExist.json @@ -0,0 +1,42 @@ +{ + "networkCallRecords" : [ { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue055108e6/messages/invalid?popreceipt=call", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "QueueNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "dd226381-4003-0028-5575-37b82d000000", + "Body" : "QueueNotFoundThe specified queue does not exist.\nRequestId:dd226381-4003-0028-5575-37b82d000000\nTime:2019-07-10T23:18:40.1101585Z", + "Date" : "Wed, 10 Jul 2019 23:18:39 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue055108e6/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "QueueNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "dd226390-4003-0028-6375-37b82d000000", + "Body" : "QueueNotFoundThe specified queue does not exist.\nRequestId:dd226390-4003-0028-6375-37b82d000000\nTime:2019-07-10T23:18:40.1591931Z", + "Date" : "Wed, 10 Jul 2019 23:18:39 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "queue055108e6" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/deleteMetadata.json b/storage/client/queue/src/test/resources/session-records/deleteMetadata.json new file mode 100644 index 0000000000000..8ba83a6d8d215 --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/deleteMetadata.json @@ -0,0 +1,106 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue679519e2", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd2263ff-4003-0028-4975-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:39 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net/queue679519e2?comp=metadata", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "Content-Length" : "0", + "x-ms-approximate-messages-count" : "0", + "x-ms-meta-metadata1" : "value1", + "StatusCode" : "200", + "x-ms-request-id" : "dd226409-4003-0028-5275-37b82d000000", + "x-ms-meta-metadata2" : "value2", + "Date" : "Wed, 10 Jul 2019 23:18:40 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue679519e2?comp=metadata", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd226418-4003-0028-6075-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:40 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net/queue679519e2?comp=metadata", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "Content-Length" : "0", + "x-ms-approximate-messages-count" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "dd226420-4003-0028-6875-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:40 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue679519e2/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd226434-4003-0028-7b75-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:40 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue679519e2", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd22644c-4003-0028-1275-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:40 GMT" + } + } ], + "variables" : [ "queue679519e2" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/deleteNonExistent.json b/storage/client/queue/src/test/resources/session-records/deleteNonExistent.json new file mode 100644 index 0000000000000..2fa6701c17acb --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/deleteNonExistent.json @@ -0,0 +1,42 @@ +{ + "networkCallRecords" : [ { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue04551c5d", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "QueueNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "dd226108-4003-0028-4e75-37b82d000000", + "Body" : "QueueNotFoundThe specified queue does not exist.\nRequestId:dd226108-4003-0028-4e75-37b82d000000\nTime:2019-07-10T23:18:38.4209499Z", + "Date" : "Wed, 10 Jul 2019 23:18:37 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue04551c5d/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "QueueNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "dd226119-4003-0028-5e75-37b82d000000", + "Body" : "QueueNotFoundThe specified queue does not exist.\nRequestId:dd226119-4003-0028-5e75-37b82d000000\nTime:2019-07-10T23:18:38.4689812Z", + "Date" : "Wed, 10 Jul 2019 23:18:37 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "queue04551c5d" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/deleteNonExistentQueue.json b/storage/client/queue/src/test/resources/session-records/deleteNonExistentQueue.json new file mode 100644 index 0000000000000..bf9105b3ccdc4 --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/deleteNonExistentQueue.json @@ -0,0 +1,42 @@ +{ + "networkCallRecords" : [ { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue82016a1d", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "QueueNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "0d290bd9-6003-009e-4476-37b6d5000000", + "Body" : "QueueNotFoundThe specified queue does not exist.\nRequestId:0d290bd9-6003-009e-4476-37b6d5000000\nTime:2019-07-10T23:24:50.9128531Z", + "Date" : "Wed, 10 Jul 2019 23:24:50 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net?prefix=queue82016a1d&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "0d290bf6-6003-009e-5b76-37b6d5000000", + "Body" : "queue82016a1d", + "Date" : "Wed, 10 Jul 2019 23:24:50 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "queue82016a1d" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/dequeueMessage.json b/storage/client/queue/src/test/resources/session-records/dequeueMessage.json new file mode 100644 index 0000000000000..6473031c5a50f --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/dequeueMessage.json @@ -0,0 +1,90 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue679346d1", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd221d34-4003-0028-3d75-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:17:52 GMT" + } + }, { + "Method" : "POST", + "Uri" : "https://sima.queue.core.windows.net/queue679346d1/messages?visibilitytimeout=0&messagettl=604800", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd221d8c-4003-0028-0a75-37b82d000000", + "Body" : "b6c999ca-9091-4109-b579-c4bca39d216dWed, 10 Jul 2019 23:17:53 GMTWed, 17 Jul 2019 23:17:53 GMTAgAAAAMAAAAAAAAA9bc/s3U31QE=Wed, 10 Jul 2019 23:17:53 GMT", + "Date" : "Wed, 10 Jul 2019 23:17:53 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net/queue679346d1/messages?numofmessages=1&visibilitytimeout=30", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "dd221da4-4003-0028-2275-37b82d000000", + "Body" : "b6c999ca-9091-4109-b579-c4bca39d216dWed, 10 Jul 2019 23:17:53 GMTWed, 17 Jul 2019 23:17:53 GMTAgAAAAMAAAAAAAAA11EwxXU31QE=Wed, 10 Jul 2019 23:18:23 GMT1test message", + "Date" : "Wed, 10 Jul 2019 23:17:53 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue679346d1/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd221da9-4003-0028-2775-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:17:53 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue679346d1", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd221db5-4003-0028-3275-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:17:53 GMT" + } + } ], + "variables" : [ "queue679346d1" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/dequeueMultipleMessages.json b/storage/client/queue/src/test/resources/session-records/dequeueMultipleMessages.json new file mode 100644 index 0000000000000..104a637b766db --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/dequeueMultipleMessages.json @@ -0,0 +1,109 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue6570759e", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd226228-4003-0028-2f75-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:38 GMT" + } + }, { + "Method" : "POST", + "Uri" : "https://sima.queue.core.windows.net/queue6570759e/messages?visibilitytimeout=0&messagettl=604800", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd22623f-4003-0028-4475-37b82d000000", + "Body" : "3d48ff69-e261-4bea-839c-ca0edfc2af4cWed, 10 Jul 2019 23:18:39 GMTWed, 17 Jul 2019 23:18:39 GMTAgAAAAMAAAAAAAAAYwGHznU31QE=Wed, 10 Jul 2019 23:18:39 GMT", + "Date" : "Wed, 10 Jul 2019 23:18:38 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "POST", + "Uri" : "https://sima.queue.core.windows.net/queue6570759e/messages?visibilitytimeout=0&messagettl=604800", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd226254-4003-0028-5375-37b82d000000", + "Body" : "fd6a25b1-b3d3-4743-b5b3-072add1a4a86Wed, 10 Jul 2019 23:18:39 GMTWed, 17 Jul 2019 23:18:39 GMTAgAAAAMAAAAAAAAAz3yOznU31QE=Wed, 10 Jul 2019 23:18:39 GMT", + "Date" : "Wed, 10 Jul 2019 23:18:38 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net/queue6570759e/messages?numofmessages=2&visibilitytimeout=30", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "dd226269-4003-0028-6475-37b82d000000", + "Body" : "3d48ff69-e261-4bea-839c-ca0edfc2af4cWed, 10 Jul 2019 23:18:39 GMTWed, 17 Jul 2019 23:18:39 GMTAgAAAAMAAAAAAAAAWsJ34HU31QE=Wed, 10 Jul 2019 23:19:09 GMT1test messagefd6a25b1-b3d3-4743-b5b3-072add1a4a86Wed, 10 Jul 2019 23:18:39 GMTWed, 17 Jul 2019 23:18:39 GMTAgAAAAMAAAAAAAAAWsJ34HU31QE=Wed, 10 Jul 2019 23:19:09 GMT1test message 2", + "Date" : "Wed, 10 Jul 2019 23:18:38 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue6570759e/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd226296-4003-0028-0975-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:38 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue6570759e", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd2262a9-4003-0028-1975-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:38 GMT" + } + } ], + "variables" : [ "queue6570759e" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/dequeueQueueDoesNotExist.json b/storage/client/queue/src/test/resources/session-records/dequeueQueueDoesNotExist.json new file mode 100644 index 0000000000000..3bef9c37aaf6e --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/dequeueQueueDoesNotExist.json @@ -0,0 +1,42 @@ +{ + "networkCallRecords" : [ { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net/queue39822dce/messages?numofmessages=1&visibilitytimeout=30", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "QueueNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "dd2260e6-4003-0028-3075-37b82d000000", + "Body" : "QueueNotFoundThe specified queue does not exist.\nRequestId:dd2260e6-4003-0028-3075-37b82d000000\nTime:2019-07-10T23:18:38.3148712Z", + "Date" : "Wed, 10 Jul 2019 23:18:37 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue39822dce/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "QueueNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "dd2260f8-4003-0028-4175-37b82d000000", + "Body" : "QueueNotFoundThe specified queue does not exist.\nRequestId:dd2260f8-4003-0028-4175-37b82d000000\nTime:2019-07-10T23:18:38.3619056Z", + "Date" : "Wed, 10 Jul 2019 23:18:37 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "queue39822dce" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/dequeueTooManyMessages.json b/storage/client/queue/src/test/resources/session-records/dequeueTooManyMessages.json new file mode 100644 index 0000000000000..757caa567efa5 --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/dequeueTooManyMessages.json @@ -0,0 +1,71 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue03015bde", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd2226b1-4003-0028-0675-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:17:59 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net/queue03015bde/messages?numofmessages=64&visibilitytimeout=30", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "OutOfRangeQueryParameterValue", + "retry-after" : "0", + "Content-Length" : "456", + "StatusCode" : "400", + "x-ms-request-id" : "dd2226cd-4003-0028-1d75-37b82d000000", + "Body" : "OutOfRangeQueryParameterValueOne of the query parameters specified in the request URI is outside the permissible range.\nRequestId:dd2226cd-4003-0028-1d75-37b82d000000\nTime:2019-07-10T23:18:00.2767678Znumofmessages64132", + "Date" : "Wed, 10 Jul 2019 23:17:59 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue03015bde/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd2226e0-4003-0028-2e75-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:17:59 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue03015bde", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd2226fd-4003-0028-4a75-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:17:59 GMT" + } + } ], + "variables" : [ "queue03015bde" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/enqueueEmptyMessage.json b/storage/client/queue/src/test/resources/session-records/enqueueEmptyMessage.json new file mode 100644 index 0000000000000..ed0aaef6517fc --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/enqueueEmptyMessage.json @@ -0,0 +1,90 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue76420ef8", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd2262ce-4003-0028-3475-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:39 GMT" + } + }, { + "Method" : "POST", + "Uri" : "https://sima.queue.core.windows.net/queue76420ef8/messages?visibilitytimeout=0&messagettl=604800", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd2262e1-4003-0028-4275-37b82d000000", + "Body" : "e1efc34f-03c7-4037-9597-6955381e8889Wed, 10 Jul 2019 23:18:39 GMTWed, 17 Jul 2019 23:18:39 GMTAgAAAAMAAAAAAAAAl6+7znU31QE=Wed, 10 Jul 2019 23:18:39 GMT", + "Date" : "Wed, 10 Jul 2019 23:18:39 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net/queue76420ef8/messages?peekonly=true", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "dd2262ef-4003-0028-5075-37b82d000000", + "Body" : "e1efc34f-03c7-4037-9597-6955381e8889Wed, 10 Jul 2019 23:18:39 GMTWed, 17 Jul 2019 23:18:39 GMT0", + "Date" : "Wed, 10 Jul 2019 23:18:39 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue76420ef8/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd2262fe-4003-0028-5e75-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:39 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue76420ef8", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd22630f-4003-0028-6f75-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:39 GMT" + } + } ], + "variables" : [ "queue76420ef8" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/enqueueMessage.json b/storage/client/queue/src/test/resources/session-records/enqueueMessage.json new file mode 100644 index 0000000000000..ff3e72aedaacf --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/enqueueMessage.json @@ -0,0 +1,90 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue17032768", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd222a23-4003-0028-4b75-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:01 GMT" + } + }, { + "Method" : "POST", + "Uri" : "https://sima.queue.core.windows.net/queue17032768/messages?visibilitytimeout=0&messagettl=604800", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd222a4a-4003-0028-6c75-37b82d000000", + "Body" : "7422f1b3-c1b1-4385-a945-6365e2e01caaWed, 10 Jul 2019 23:18:01 GMTWed, 17 Jul 2019 23:18:01 GMTAgAAAAMAAAAAAAAAQm1FuHU31QE=Wed, 10 Jul 2019 23:18:01 GMT", + "Date" : "Wed, 10 Jul 2019 23:18:01 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net/queue17032768/messages?peekonly=true", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "dd222a74-4003-0028-1275-37b82d000000", + "Body" : "7422f1b3-c1b1-4385-a945-6365e2e01caaWed, 10 Jul 2019 23:18:01 GMTWed, 17 Jul 2019 23:18:01 GMT0test message", + "Date" : "Wed, 10 Jul 2019 23:18:01 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue17032768/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd222aa3-4003-0028-3975-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:01 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue17032768", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd222ac4-4003-0028-5675-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:01 GMT" + } + } ], + "variables" : [ "queue17032768" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/enqueueQueueDoesNotExist.json b/storage/client/queue/src/test/resources/session-records/enqueueQueueDoesNotExist.json new file mode 100644 index 0000000000000..9433eea40c38b --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/enqueueQueueDoesNotExist.json @@ -0,0 +1,43 @@ +{ + "networkCallRecords" : [ { + "Method" : "POST", + "Uri" : "https://sima.queue.core.windows.net/queue39910e47/messages?visibilitytimeout=0&messagettl=604800", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "QueueNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "dd2229a6-4003-0028-6475-37b82d000000", + "Body" : "QueueNotFoundThe specified queue does not exist.\nRequestId:dd2229a6-4003-0028-6475-37b82d000000\nTime:2019-07-10T23:18:01.6777634Z", + "Date" : "Wed, 10 Jul 2019 23:18:01 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue39910e47/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "QueueNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "dd2229bd-4003-0028-7575-37b82d000000", + "Body" : "QueueNotFoundThe specified queue does not exist.\nRequestId:dd2229bd-4003-0028-7575-37b82d000000\nTime:2019-07-10T23:18:01.7277985Z", + "Date" : "Wed, 10 Jul 2019 23:18:01 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "queue39910e47" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/enqueueShortTimeToLiveMessage.json b/storage/client/queue/src/test/resources/session-records/enqueueShortTimeToLiveMessage.json new file mode 100644 index 0000000000000..bb6b2172664f2 --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/enqueueShortTimeToLiveMessage.json @@ -0,0 +1,90 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue69359315", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd221f37-4003-0028-1c75-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:17:54 GMT" + } + }, { + "Method" : "POST", + "Uri" : "https://sima.queue.core.windows.net/queue69359315/messages?visibilitytimeout=0&messagettl=2", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd221f43-4003-0028-2775-37b82d000000", + "Body" : "c96e7db1-1d4a-4743-b165-a5835968722aWed, 10 Jul 2019 23:17:54 GMTWed, 10 Jul 2019 23:17:56 GMTAgAAAAMAAAAAAAAApcYOtHU31QE=Wed, 10 Jul 2019 23:17:54 GMT", + "Date" : "Wed, 10 Jul 2019 23:17:54 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net/queue69359315/messages?peekonly=true", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "dd222634-4003-0028-1675-37b82d000000", + "Body" : "", + "Date" : "Wed, 10 Jul 2019 23:17:59 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue69359315/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd22264c-4003-0028-2c75-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:17:59 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue69359315", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd222666-4003-0028-4375-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:17:59 GMT" + } + } ], + "variables" : [ "queue69359315" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/getAccessPolicy.json b/storage/client/queue/src/test/resources/session-records/getAccessPolicy.json new file mode 100644 index 0000000000000..79f9317b619d1 --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/getAccessPolicy.json @@ -0,0 +1,71 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue276184e3", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd222bac-4003-0028-2175-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:02 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net/queue276184e3?comp=acl", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "dd222bc0-4003-0028-3175-37b82d000000", + "Body" : "", + "Date" : "Wed, 10 Jul 2019 23:18:02 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue276184e3/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd222be3-4003-0028-4d75-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:02 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue276184e3", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd222bfe-4003-0028-6375-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:02 GMT" + } + } ], + "variables" : [ "queue276184e3" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/getAccessPolicyQueueDoesNotExist.json b/storage/client/queue/src/test/resources/session-records/getAccessPolicyQueueDoesNotExist.json new file mode 100644 index 0000000000000..8c772f655188e --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/getAccessPolicyQueueDoesNotExist.json @@ -0,0 +1,42 @@ +{ + "networkCallRecords" : [ { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net/queue66823709?comp=acl", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "QueueNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "dd22604d-4003-0028-2a75-37b82d000000", + "Body" : "QueueNotFoundThe specified queue does not exist.\nRequestId:dd22604d-4003-0028-2a75-37b82d000000\nTime:2019-07-10T23:18:37.8315254Z", + "Date" : "Wed, 10 Jul 2019 23:18:37 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue66823709/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "QueueNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "dd226056-4003-0028-3275-37b82d000000", + "Body" : "QueueNotFoundThe specified queue does not exist.\nRequestId:dd226056-4003-0028-3275-37b82d000000\nTime:2019-07-10T23:18:37.8795608Z", + "Date" : "Wed, 10 Jul 2019 23:18:37 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "queue66823709" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/getProperties.json b/storage/client/queue/src/test/resources/session-records/getProperties.json new file mode 100644 index 0000000000000..a7c0a0ec5332d --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/getProperties.json @@ -0,0 +1,72 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue36601253", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd2227b8-4003-0028-6075-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:00 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net/queue36601253?comp=metadata", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "Content-Length" : "0", + "x-ms-approximate-messages-count" : "0", + "x-ms-meta-metadata1" : "value1", + "StatusCode" : "200", + "x-ms-request-id" : "dd2227d1-4003-0028-7675-37b82d000000", + "x-ms-meta-metadata2" : "value2", + "Date" : "Wed, 10 Jul 2019 23:18:00 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue36601253/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd2227f9-4003-0028-1775-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:00 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue36601253", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd222807-4003-0028-2575-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:00 GMT" + } + } ], + "variables" : [ "queue36601253" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/getPropertiesQueueDoesNotExist.json b/storage/client/queue/src/test/resources/session-records/getPropertiesQueueDoesNotExist.json new file mode 100644 index 0000000000000..fe98b22946df5 --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/getPropertiesQueueDoesNotExist.json @@ -0,0 +1,42 @@ +{ + "networkCallRecords" : [ { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net/queue7527481d?comp=metadata", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "QueueNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "dd222681-4003-0028-5b75-37b82d000000", + "Body" : "QueueNotFoundThe specified queue does not exist.\nRequestId:dd222681-4003-0028-5b75-37b82d000000\nTime:2019-07-10T23:18:00.1126512Z", + "Date" : "Wed, 10 Jul 2019 23:17:59 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue7527481d/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "QueueNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "dd22269d-4003-0028-7375-37b82d000000", + "Body" : "QueueNotFoundThe specified queue does not exist.\nRequestId:dd22269d-4003-0028-7375-37b82d000000\nTime:2019-07-10T23:18:00.1626872Z", + "Date" : "Wed, 10 Jul 2019 23:17:59 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "queue7527481d" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/getQueueDoesNotCreateAQueue.json b/storage/client/queue/src/test/resources/session-records/getQueueDoesNotCreateAQueue.json new file mode 100644 index 0000000000000..7776d4fed4783 --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/getQueueDoesNotCreateAQueue.json @@ -0,0 +1,43 @@ +{ + "networkCallRecords" : [ { + "Method" : "POST", + "Uri" : "https://sima.queue.core.windows.net/queue48695d7f/messages?visibilitytimeout=0&messagettl=604800", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "QueueNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "0d290a18-6003-009e-3676-37b6d5000000", + "Body" : "QueueNotFoundThe specified queue does not exist.\nRequestId:0d290a18-6003-009e-3676-37b6d5000000\nTime:2019-07-10T23:24:49.7390111Z", + "Date" : "Wed, 10 Jul 2019 23:24:49 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net?prefix=queue48695d7f&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "0d290a2f-6003-009e-4876-37b6d5000000", + "Body" : "queue48695d7f", + "Date" : "Wed, 10 Jul 2019 23:24:49 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "queue48695d7f" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/listQueues.json b/storage/client/queue/src/test/resources/session-records/listQueues.json new file mode 100644 index 0000000000000..361f47abd400a --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/listQueues.json @@ -0,0 +1,186 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue455724b60", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "0d2907f4-6003-009e-0976-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:48 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue455724b61", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "0d290805-6003-009e-1376-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:48 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue455724b62", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "0d29080b-6003-009e-1876-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:48 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net?prefix=queue455724b6&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "0d290816-6003-009e-2276-37b6d5000000", + "Body" : "queue455724b6queue455724b60queue455724b61queue455724b62", + "Date" : "Wed, 10 Jul 2019 23:24:48 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net?prefix=queue455724b6&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "0d29083e-6003-009e-4676-37b6d5000000", + "Body" : "queue455724b6queue455724b60queue455724b61queue455724b62", + "Date" : "Wed, 10 Jul 2019 23:24:48 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue455724b60/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "0d290871-6003-009e-6e76-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:48 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue455724b60", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "0d290896-6003-009e-0676-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:48 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue455724b61/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "0d2908bc-6003-009e-2476-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:48 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue455724b61", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "0d2908df-6003-009e-3e76-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:49 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue455724b62/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "0d2908fd-6003-009e-5676-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:49 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue455724b62", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "0d29091f-6003-009e-6a76-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:49 GMT" + } + } ], + "variables" : [ "queue455724b6" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/listQueuesIncludeMetadata.json b/storage/client/queue/src/test/resources/session-records/listQueuesIncludeMetadata.json new file mode 100644 index 0000000000000..a0e836cf26701 --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/listQueuesIncludeMetadata.json @@ -0,0 +1,186 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue58738ae80", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "0d290c20-6003-009e-7b76-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:51 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue58738ae81", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "0d290c34-6003-009e-0a76-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:51 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue58738ae82", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "0d290c4e-6003-009e-1f76-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:51 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net?prefix=queue58738ae8&include=metadata&comp=list", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "0d290c6b-6003-009e-3376-37b6d5000000", + "Body" : "queue58738ae8queue58738ae80value1value2queue58738ae81queue58738ae82value1value2", + "Date" : "Wed, 10 Jul 2019 23:24:51 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net?prefix=queue58738ae8&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "0d290c8e-6003-009e-5176-37b6d5000000", + "Body" : "queue58738ae8queue58738ae80queue58738ae81queue58738ae82", + "Date" : "Wed, 10 Jul 2019 23:24:51 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue58738ae80/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "0d290caa-6003-009e-6876-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:51 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue58738ae80", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "0d290cc1-6003-009e-7a76-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:51 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue58738ae81/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "0d290cde-6003-009e-1176-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:51 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue58738ae81", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "0d290cf2-6003-009e-2376-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:51 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue58738ae82/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "0d290d14-6003-009e-4076-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:51 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue58738ae82", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "0d290d2b-6003-009e-5476-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:51 GMT" + } + } ], + "variables" : [ "queue58738ae8" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/listQueuesWithPrefix.json b/storage/client/queue/src/test/resources/session-records/listQueuesWithPrefix.json new file mode 100644 index 0000000000000..ff107058e29fc --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/listQueuesWithPrefix.json @@ -0,0 +1,186 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue423382efprefix0", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "0d290acd-6003-009e-5476-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:50 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue423382ef1", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "0d290ae3-6003-009e-6876-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:50 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue423382efprefix2", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "0d290afd-6003-009e-8076-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:50 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net?prefix=queue423382efprefix&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "0d290b0d-6003-009e-0f76-37b6d5000000", + "Body" : "queue423382efprefixqueue423382efprefix0queue423382efprefix2", + "Date" : "Wed, 10 Jul 2019 23:24:50 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net?prefix=queue423382ef&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "0d290b16-6003-009e-1776-37b6d5000000", + "Body" : "queue423382efqueue423382ef1queue423382efprefix0queue423382efprefix2", + "Date" : "Wed, 10 Jul 2019 23:24:50 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue423382ef1/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "0d290b38-6003-009e-3576-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:50 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue423382ef1", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "0d290b4c-6003-009e-4776-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:50 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue423382efprefix0/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "0d290b60-6003-009e-5976-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:50 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue423382efprefix0", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "0d290b71-6003-009e-6676-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:50 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue423382efprefix2/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "0d290b81-6003-009e-7576-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:50 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue423382efprefix2", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "0d290b9a-6003-009e-0b76-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:50 GMT" + } + } ], + "variables" : [ "queue423382ef" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/peekMessage.json b/storage/client/queue/src/test/resources/session-records/peekMessage.json new file mode 100644 index 0000000000000..540c460785a11 --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/peekMessage.json @@ -0,0 +1,90 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue54577e60", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd225fa8-4003-0028-0d75-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:36 GMT" + } + }, { + "Method" : "POST", + "Uri" : "https://sima.queue.core.windows.net/queue54577e60/messages?visibilitytimeout=0&messagettl=604800", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd225fb8-4003-0028-1c75-37b82d000000", + "Body" : "53096a37-63bf-45d9-9172-4c8713ff282eWed, 10 Jul 2019 23:18:37 GMTWed, 17 Jul 2019 23:18:37 GMTAgAAAAMAAAAAAAAATsJgzXU31QE=Wed, 10 Jul 2019 23:18:37 GMT", + "Date" : "Wed, 10 Jul 2019 23:18:36 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net/queue54577e60/messages?peekonly=true", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "dd225fd2-4003-0028-3375-37b82d000000", + "Body" : "53096a37-63bf-45d9-9172-4c8713ff282eWed, 10 Jul 2019 23:18:37 GMTWed, 17 Jul 2019 23:18:37 GMT0test message", + "Date" : "Wed, 10 Jul 2019 23:18:36 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue54577e60/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd225fe6-4003-0028-4775-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:36 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue54577e60", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd225ff7-4003-0028-5875-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:37 GMT" + } + } ], + "variables" : [ "queue54577e60" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/peekMultipleMessages.json b/storage/client/queue/src/test/resources/session-records/peekMultipleMessages.json new file mode 100644 index 0000000000000..5ea0a89b15f98 --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/peekMultipleMessages.json @@ -0,0 +1,109 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue17925938", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd222afc-4003-0028-0875-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:01 GMT" + } + }, { + "Method" : "POST", + "Uri" : "https://sima.queue.core.windows.net/queue17925938/messages?visibilitytimeout=0&messagettl=604800", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd222b1e-4003-0028-2375-37b82d000000", + "Body" : "86c3b192-2c4f-4bd4-89bf-07553c141ac0Wed, 10 Jul 2019 23:18:02 GMTWed, 17 Jul 2019 23:18:02 GMTAgAAAAMAAAAAAAAAI8dyuHU31QE=Wed, 10 Jul 2019 23:18:02 GMT", + "Date" : "Wed, 10 Jul 2019 23:18:01 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "POST", + "Uri" : "https://sima.queue.core.windows.net/queue17925938/messages?visibilitytimeout=0&messagettl=604800", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd222b4a-4003-0028-4775-37b82d000000", + "Body" : "1b2d50b7-3540-4dd4-a480-8549b5207fe7Wed, 10 Jul 2019 23:18:02 GMTWed, 17 Jul 2019 23:18:02 GMTAgAAAAMAAAAAAAAAqWl6uHU31QE=Wed, 10 Jul 2019 23:18:02 GMT", + "Date" : "Wed, 10 Jul 2019 23:18:01 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net/queue17925938/messages?numofmessages=2&peekonly=true", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "dd222b67-4003-0028-6175-37b82d000000", + "Body" : "86c3b192-2c4f-4bd4-89bf-07553c141ac0Wed, 10 Jul 2019 23:18:02 GMTWed, 17 Jul 2019 23:18:02 GMT0test message1b2d50b7-3540-4dd4-a480-8549b5207fe7Wed, 10 Jul 2019 23:18:02 GMTWed, 17 Jul 2019 23:18:02 GMT0test message 2", + "Date" : "Wed, 10 Jul 2019 23:18:01 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue17925938/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd222b7e-4003-0028-7675-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:01 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue17925938", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd222b8e-4003-0028-0675-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:01 GMT" + } + } ], + "variables" : [ "queue17925938" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/peekQueueDoesNotExist.json b/storage/client/queue/src/test/resources/session-records/peekQueueDoesNotExist.json new file mode 100644 index 0000000000000..c9de737c16179 --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/peekQueueDoesNotExist.json @@ -0,0 +1,42 @@ +{ + "networkCallRecords" : [ { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net/queue5442745c/messages?peekonly=true", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "QueueNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "dd221dd8-4003-0028-5075-37b82d000000", + "Body" : "QueueNotFoundThe specified queue does not exist.\nRequestId:dd221dd8-4003-0028-5075-37b82d000000\nTime:2019-07-10T23:17:53.9252561Z", + "Date" : "Wed, 10 Jul 2019 23:17:53 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue5442745c/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "QueueNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "dd221df7-4003-0028-6d75-37b82d000000", + "Body" : "QueueNotFoundThe specified queue does not exist.\nRequestId:dd221df7-4003-0028-6d75-37b82d000000\nTime:2019-07-10T23:17:54.0093158Z", + "Date" : "Wed, 10 Jul 2019 23:17:53 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "queue5442745c" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/peekTooManyMessages.json b/storage/client/queue/src/test/resources/session-records/peekTooManyMessages.json new file mode 100644 index 0000000000000..f653e97e1e0ce --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/peekTooManyMessages.json @@ -0,0 +1,71 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue80227035", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd22612f-4003-0028-7275-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:38 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net/queue80227035/messages?numofmessages=64&peekonly=true", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "OutOfRangeQueryParameterValue", + "retry-after" : "0", + "Content-Length" : "456", + "StatusCode" : "400", + "x-ms-request-id" : "dd226138-4003-0028-7a75-37b82d000000", + "Body" : "OutOfRangeQueryParameterValueOne of the query parameters specified in the request URI is outside the permissible range.\nRequestId:dd226138-4003-0028-7a75-37b82d000000\nTime:2019-07-10T23:18:38.5780592Znumofmessages64132", + "Date" : "Wed, 10 Jul 2019 23:18:38 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue80227035/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd22613d-4003-0028-7f75-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:38 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue80227035", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd226149-4003-0028-0975-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:38 GMT" + } + } ], + "variables" : [ "queue80227035" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/setAccessPolicy.json b/storage/client/queue/src/test/resources/session-records/setAccessPolicy.json new file mode 100644 index 0000000000000..ac6e9881a669f --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/setAccessPolicy.json @@ -0,0 +1,88 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue656812ca", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd225f53-4003-0028-4075-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:36 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue656812ca?comp=acl", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd225f6a-4003-0028-5575-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:36 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net/queue656812ca?comp=acl", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "dd225f7e-4003-0028-6675-37b82d000000", + "Body" : "testpermission2000-01-01T00:00:00.0000000Z2020-01-01T00:00:00.0000000Zraup", + "Date" : "Wed, 10 Jul 2019 23:18:36 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue656812ca/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd225f8c-4003-0028-7475-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:36 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue656812ca", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd225f98-4003-0028-7e75-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:36 GMT" + } + } ], + "variables" : [ "queue656812ca" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/setAccessPolicyQueueDoesNotExist.json b/storage/client/queue/src/test/resources/session-records/setAccessPolicyQueueDoesNotExist.json new file mode 100644 index 0000000000000..b2b42bce18c37 --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/setAccessPolicyQueueDoesNotExist.json @@ -0,0 +1,43 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue01052e33?comp=acl", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "InvalidXmlDocument", + "retry-after" : "0", + "Content-Length" : "294", + "StatusCode" : "400", + "x-ms-request-id" : "dd22645d-4003-0028-2375-37b82d000000", + "Body" : "InvalidXmlDocumentXML specified is not syntactically valid.\nRequestId:dd22645d-4003-0028-2375-37b82d000000\nTime:2019-07-10T23:18:40.8086534Z00", + "Date" : "Wed, 10 Jul 2019 23:18:40 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue01052e33/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "QueueNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "dd22646a-4003-0028-2f75-37b82d000000", + "Body" : "QueueNotFoundThe specified queue does not exist.\nRequestId:dd22646a-4003-0028-2f75-37b82d000000\nTime:2019-07-10T23:18:40.8566884Z", + "Date" : "Wed, 10 Jul 2019 23:18:40 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "queue01052e33" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/setInvalidAccessPolicy.json b/storage/client/queue/src/test/resources/session-records/setInvalidAccessPolicy.json new file mode 100644 index 0000000000000..fe186f2b4ac1c --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/setInvalidAccessPolicy.json @@ -0,0 +1,72 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue424460ef", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd226338-4003-0028-1475-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:39 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue424460ef?comp=acl", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "InvalidXmlDocument", + "retry-after" : "0", + "Content-Length" : "371", + "StatusCode" : "400", + "x-ms-request-id" : "dd22634c-4003-0028-2575-37b82d000000", + "Body" : "InvalidXmlDocumentXML specified is not syntactically valid.\nRequestId:dd22634c-4003-0028-2575-37b82d000000\nTime:2019-07-10T23:18:39.9250246Z1304Signed identifier ID cannot be empty or over 64 characters in length", + "Date" : "Wed, 10 Jul 2019 23:18:39 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue424460ef/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd22635d-4003-0028-3675-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:39 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue424460ef", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd226363-4003-0028-3a75-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:39 GMT" + } + } ], + "variables" : [ "queue424460ef" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/setInvalidMetadata.json b/storage/client/queue/src/test/resources/session-records/setInvalidMetadata.json new file mode 100644 index 0000000000000..eb9faafed36f9 --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/setInvalidMetadata.json @@ -0,0 +1,71 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue38693e14", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd22272a-4003-0028-7175-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:17:59 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue38693e14?comp=metadata", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "EmptyMetadataKey", + "retry-after" : "0", + "Content-Length" : "285", + "StatusCode" : "400", + "x-ms-request-id" : "dd22274f-4003-0028-0b75-37b82d000000", + "Body" : "EmptyMetadataKeyThe key for one of the metadata key-value pairs is empty.\nRequestId:dd22274f-4003-0028-0b75-37b82d000000\nTime:2019-07-10T23:18:00.5359517Zbad metadata", + "Date" : "Wed, 10 Jul 2019 23:18:00 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue38693e14/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd222779-4003-0028-2875-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:00 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue38693e14", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd222798-4003-0028-4375-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:00 GMT" + } + } ], + "variables" : [ "queue38693e14" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/setMetadata.json b/storage/client/queue/src/test/resources/session-records/setMetadata.json new file mode 100644 index 0000000000000..5d60ce89a352d --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/setMetadata.json @@ -0,0 +1,88 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue625780b6", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd2263a4-4003-0028-7675-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:39 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue625780b6?comp=metadata", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd2263c0-4003-0028-0f75-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:39 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net/queue625780b6?comp=metadata", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "Content-Length" : "0", + "x-ms-approximate-messages-count" : "0", + "x-ms-meta-metadata1" : "value1", + "StatusCode" : "200", + "x-ms-request-id" : "dd2263d2-4003-0028-2075-37b82d000000", + "x-ms-meta-metadata2" : "value2", + "Date" : "Wed, 10 Jul 2019 23:18:39 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue625780b6/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd2263dd-4003-0028-2a75-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:39 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue625780b6", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd2263ea-4003-0028-3775-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:39 GMT" + } + } ], + "variables" : [ "queue625780b6" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/setMetadataQueueDoesNotExist.json b/storage/client/queue/src/test/resources/session-records/setMetadataQueueDoesNotExist.json new file mode 100644 index 0000000000000..4d7536d402ced --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/setMetadataQueueDoesNotExist.json @@ -0,0 +1,42 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue570099c0?comp=metadata", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "QueueNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "dd2260d2-4003-0028-2175-37b82d000000", + "Body" : "QueueNotFoundThe specified queue does not exist.\nRequestId:dd2260d2-4003-0028-2175-37b82d000000\nTime:2019-07-10T23:18:38.2057923Z", + "Date" : "Wed, 10 Jul 2019 23:18:37 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue570099c0/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "QueueNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "dd2260d9-4003-0028-2775-37b82d000000", + "Body" : "QueueNotFoundThe specified queue does not exist.\nRequestId:dd2260d9-4003-0028-2775-37b82d000000\nTime:2019-07-10T23:18:38.2538267Z", + "Date" : "Wed, 10 Jul 2019 23:18:37 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "queue570099c0" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/setProperties.json b/storage/client/queue/src/test/resources/session-records/setProperties.json new file mode 100644 index 0000000000000..3c832f439b708 --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/setProperties.json @@ -0,0 +1,114 @@ +{ + "networkCallRecords" : [ { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net?restype=service&comp=properties", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "0d2906b5-6003-009e-0476-37b6d5000000", + "Body" : "1.0falsefalsefalsefalse1.0truetruetrue71.0falsefalse", + "Date" : "Wed, 10 Jul 2019 23:24:47 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net?restype=service&comp=properties", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "0d2906d0-6003-009e-1a76-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:47 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net?restype=service&comp=properties", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "0d290712-6003-009e-4e76-37b6d5000000", + "Body" : "1.0falsetruetruetrue31.0truefalsetrue31.0truefalsetrue3", + "Date" : "Wed, 10 Jul 2019 23:24:47 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net?restype=service&comp=properties", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "0d290721-6003-009e-5b76-37b6d5000000", + "Date" : "Wed, 10 Jul 2019 23:24:48 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net?restype=service&comp=properties", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "0d290739-6003-009e-7076-37b6d5000000", + "Body" : "1.0falsefalsefalsefalse1.0truetruetrue71.0falsefalse", + "Date" : "Wed, 10 Jul 2019 23:24:48 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net?prefix=queue49487893&include=&comp=list", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "0d29074d-6003-009e-0176-37b6d5000000", + "Body" : "queue49487893", + "Date" : "Wed, 10 Jul 2019 23:24:48 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "queue49487893" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/setTooManyAccessPolicies.json b/storage/client/queue/src/test/resources/session-records/setTooManyAccessPolicies.json new file mode 100644 index 0000000000000..adee338b14141 --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/setTooManyAccessPolicies.json @@ -0,0 +1,72 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue265747a2", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd22600f-4003-0028-7075-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:37 GMT" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue265747a2?comp=acl", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "InvalidXmlDocument", + "retry-after" : "0", + "Content-Length" : "294", + "StatusCode" : "400", + "x-ms-request-id" : "dd226022-4003-0028-0175-37b82d000000", + "Body" : "InvalidXmlDocumentXML specified is not syntactically valid.\nRequestId:dd226022-4003-0028-0175-37b82d000000\nTime:2019-07-10T23:18:37.6694120Z00", + "Date" : "Wed, 10 Jul 2019 23:18:37 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue265747a2/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd226034-4003-0028-1175-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:37 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue265747a2", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd226043-4003-0028-2075-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:37 GMT" + } + } ], + "variables" : [ "queue265747a2" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/updateMessage.json b/storage/client/queue/src/test/resources/session-records/updateMessage.json new file mode 100644 index 0000000000000..46e184bda045c --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/updateMessage.json @@ -0,0 +1,128 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue4236461c", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd222c30-4003-0028-0f75-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:02 GMT" + } + }, { + "Method" : "POST", + "Uri" : "https://sima.queue.core.windows.net/queue4236461c/messages?visibilitytimeout=0&messagettl=604800", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd222c40-4003-0028-1c75-37b82d000000", + "Body" : "c3781181-9103-468e-b645-f6dbb100bd9cWed, 10 Jul 2019 23:18:02 GMTWed, 17 Jul 2019 23:18:02 GMTAgAAAAMAAAAAAAAAjQ/SuHU31QE=Wed, 10 Jul 2019 23:18:02 GMT", + "Date" : "Wed, 10 Jul 2019 23:18:02 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net/queue4236461c/messages?numofmessages=1&visibilitytimeout=30", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "dd222c62-4003-0028-3b75-37b82d000000", + "Body" : "c3781181-9103-468e-b645-f6dbb100bd9cWed, 10 Jul 2019 23:18:02 GMTWed, 17 Jul 2019 23:18:02 GMTAgAAAAMAAAAAAAAAEAO9ynU31QE=Wed, 10 Jul 2019 23:18:32 GMT1test message", + "Date" : "Wed, 10 Jul 2019 23:18:02 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue4236461c/messages/c3781181-9103-468e-b645-f6dbb100bd9c?popreceipt=AgAAAAMAAAAAAAAAEAO9ynU31QE%3d&visibilitytimeout=1", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-time-next-visible" : "Wed, 10 Jul 2019 23:18:04 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd222c7f-4003-0028-5475-37b82d000000", + "x-ms-popreceipt" : "AwAAAAMAAAAAAAAAZuN9uXU31QEBAAAA", + "Date" : "Wed, 10 Jul 2019 23:18:02 GMT" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net/queue4236461c/messages?peekonly=true", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "dd2230d0-4003-0028-1b75-37b82d000000", + "Body" : "c3781181-9103-468e-b645-f6dbb100bd9cWed, 10 Jul 2019 23:18:02 GMTWed, 17 Jul 2019 23:18:02 GMT1updated test message", + "Date" : "Wed, 10 Jul 2019 23:18:04 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue4236461c/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd2230e9-4003-0028-2e75-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:04 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue4236461c", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd223113-4003-0028-4f75-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:04 GMT" + } + } ], + "variables" : [ "queue4236461c" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/updateMessageInvalidMessageId.json b/storage/client/queue/src/test/resources/session-records/updateMessageInvalidMessageId.json new file mode 100644 index 0000000000000..eae58afb9650c --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/updateMessageInvalidMessageId.json @@ -0,0 +1,110 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue10019121", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd223139-4003-0028-6d75-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:04 GMT" + } + }, { + "Method" : "POST", + "Uri" : "https://sima.queue.core.windows.net/queue10019121/messages?visibilitytimeout=0&messagettl=604800", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd223159-4003-0028-0475-37b82d000000", + "Body" : "e3dbec12-5e3c-47f4-abd9-fbdf6e44746dWed, 10 Jul 2019 23:18:05 GMTWed, 17 Jul 2019 23:18:05 GMTAgAAAAMAAAAAAAAA7UtBunU31QE=Wed, 10 Jul 2019 23:18:05 GMT", + "Date" : "Wed, 10 Jul 2019 23:18:04 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net/queue10019121/messages?numofmessages=1&visibilitytimeout=30", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "dd223169-4003-0028-1475-37b82d000000", + "Body" : "e3dbec12-5e3c-47f4-abd9-fbdf6e44746dWed, 10 Jul 2019 23:18:05 GMTWed, 17 Jul 2019 23:18:05 GMTAgAAAAMAAAAAAAAAc5EqzHU31QE=Wed, 10 Jul 2019 23:18:35 GMT1test message", + "Date" : "Wed, 10 Jul 2019 23:18:04 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue10019121/messages/e3dbec12-5e3c-47f4-abd9-fbdf6e44746drandom?popreceipt=AgAAAAMAAAAAAAAAc5EqzHU31QE%3d&visibilitytimeout=1", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "MessageNotFound", + "retry-after" : "0", + "Content-Length" : "221", + "StatusCode" : "404", + "x-ms-request-id" : "dd22317f-4003-0028-2775-37b82d000000", + "Body" : "MessageNotFoundThe specified message does not exist.\nRequestId:dd22317f-4003-0028-2775-37b82d000000\nTime:2019-07-10T23:18:05.3974051Z", + "Date" : "Wed, 10 Jul 2019 23:18:04 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue10019121/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd223195-4003-0028-3975-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:04 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue10019121", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd2231a9-4003-0028-4975-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:05 GMT" + } + } ], + "variables" : [ "queue10019121" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/updateMessageInvalidPopReceipt.json b/storage/client/queue/src/test/resources/session-records/updateMessageInvalidPopReceipt.json new file mode 100644 index 0000000000000..f7795c878f27f --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/updateMessageInvalidPopReceipt.json @@ -0,0 +1,110 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue41380e30", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd22326c-4003-0028-6c75-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:05 GMT" + } + }, { + "Method" : "POST", + "Uri" : "https://sima.queue.core.windows.net/queue41380e30/messages?visibilitytimeout=0&messagettl=604800", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "dd22329c-4003-0028-1475-37b82d000000", + "Body" : "8900ad74-7404-4cd2-8b4b-41e70995dc1fWed, 10 Jul 2019 23:18:06 GMTWed, 17 Jul 2019 23:18:06 GMTAgAAAAMAAAAAAAAA/TyvunU31QE=Wed, 10 Jul 2019 23:18:06 GMT", + "Date" : "Wed, 10 Jul 2019 23:18:05 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "GET", + "Uri" : "https://sima.queue.core.windows.net/queue41380e30/messages?numofmessages=1&visibilitytimeout=30", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "Cache-Control" : "no-cache", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "dd2232d5-4003-0028-4575-37b82d000000", + "Body" : "8900ad74-7404-4cd2-8b4b-41e70995dc1fWed, 10 Jul 2019 23:18:06 GMTWed, 17 Jul 2019 23:18:06 GMTAgAAAAMAAAAAAAAA+kWZzHU31QE=Wed, 10 Jul 2019 23:18:36 GMT1test message", + "Date" : "Wed, 10 Jul 2019 23:18:05 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue41380e30/messages/8900ad74-7404-4cd2-8b4b-41e70995dc1f?popreceipt=AgAAAAMAAAAAAAAA%2bkWZzHU31QE%3drandom&visibilitytimeout=1", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "InvalidQueryParameterValue", + "retry-after" : "0", + "Content-Length" : "444", + "StatusCode" : "400", + "x-ms-request-id" : "dd2232ff-4003-0028-6d75-37b82d000000", + "Body" : "InvalidQueryParameterValueValue for one of the query parameters specified in the request URI is invalid.\nRequestId:dd2232ff-4003-0028-6d75-37b82d000000\nTime:2019-07-10T23:18:06.1209188ZpopreceiptAgAAAAMAAAAAAAAA+kWZzHU31QE=randomInvalid pop receipt format", + "Date" : "Wed, 10 Jul 2019 23:18:05 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue41380e30/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd22331d-4003-0028-0a75-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:05 GMT" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue41380e30", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "204", + "x-ms-request-id" : "dd223333-4003-0028-2075-37b82d000000", + "Date" : "Wed, 10 Jul 2019 23:18:05 GMT" + } + } ], + "variables" : [ "queue41380e30" ] +} \ No newline at end of file diff --git a/storage/client/queue/src/test/resources/session-records/updateMessageQueueDoesNotExist.json b/storage/client/queue/src/test/resources/session-records/updateMessageQueueDoesNotExist.json new file mode 100644 index 0000000000000..9341ea4a79897 --- /dev/null +++ b/storage/client/queue/src/test/resources/session-records/updateMessageQueueDoesNotExist.json @@ -0,0 +1,43 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://sima.queue.core.windows.net/queue77530b22/messages/doesn't?popreceipt=exist&visibilitytimeout=5", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "InvalidQueryParameterValue", + "retry-after" : "0", + "Content-Length" : "415", + "StatusCode" : "400", + "x-ms-request-id" : "dd2229e1-4003-0028-1475-37b82d000000", + "Body" : "InvalidQueryParameterValueValue for one of the query parameters specified in the request URI is invalid.\nRequestId:dd2229e1-4003-0028-1475-37b82d000000\nTime:2019-07-10T23:18:01.7878412ZpopreceiptexistInvalid pop receipt format", + "Date" : "Wed, 10 Jul 2019 23:18:01 GMT", + "Content-Type" : "application/xml" + } + }, { + "Method" : "DELETE", + "Uri" : "https://sima.queue.core.windows.net/queue77530b22/messages", + "Headers" : { + "x-ms-version" : "2018-03-28", + "User-Agent" : "azsdk-java-storage-queue/1.0.0-SNAPSHOT 1.8.0_201; Windows 10 10.0" + }, + "Response" : { + "x-ms-version" : "2018-03-28", + "Server" : "Windows-Azure-Queue/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-error-code" : "QueueNotFound", + "retry-after" : "0", + "Content-Length" : "217", + "StatusCode" : "404", + "x-ms-request-id" : "dd2229fb-4003-0028-2a75-37b82d000000", + "Body" : "QueueNotFoundThe specified queue does not exist.\nRequestId:dd2229fb-4003-0028-2a75-37b82d000000\nTime:2019-07-10T23:18:01.8368763Z", + "Date" : "Wed, 10 Jul 2019 23:18:01 GMT", + "Content-Type" : "application/xml" + } + } ], + "variables" : [ "queue77530b22" ] +} \ No newline at end of file From b602214e0460ea0582fbc960046e010381213daf Mon Sep 17 00:00:00 2001 From: Jianghao Lu Date: Tue, 23 Jul 2019 17:14:12 -0700 Subject: [PATCH 07/17] Address code review feedback in AutoRest --- .../storage/blob/ContainerAsyncClient.java | 2 +- .../blob/implementation/AppendBlobsImpl.java | 8 +- .../blob/implementation/BlobsImpl.java | 10 +- .../blob/implementation/BlockBlobsImpl.java | 8 +- .../blob/implementation/ContainersImpl.java | 15 +- .../blob/implementation/PageBlobsImpl.java | 12 +- .../blob/implementation/ServicesImpl.java | 6 +- ...pper.java => SignedIdentifierWrapper.java} | 18 +- .../blob/implementation/package-info.java | 2 +- .../blob/models/BlobHierarchyListSegment.java | 2 + .../azure/storage/blob/models/BlobItem.java | 26 ++- .../storage/blob/models/package-info.java | 2 +- .../com/azure/storage/blob/APISpec.groovy | 2 +- storage/client/blob/swagger/blob.json | 77 ++------ .../file/implementation/DirectorysImpl.java | 6 +- .../file/implementation/FilesImpl.java | 6 +- .../file/implementation/ServicesImpl.java | 6 +- .../file/implementation/SharesImpl.java | 6 +- .../file/implementation/package-info.java | 2 +- .../storage/file/models/package-info.java | 2 +- .../queue/implementation/MessageIdsImpl.java | 6 +- .../queue/implementation/MessagesImpl.java | 6 +- .../queue/implementation/QueuesImpl.java | 6 +- .../queue/implementation/ServicesImpl.java | 6 +- .../queue/implementation/package-info.java | 2 +- .../queue/models/MessagesPeekResponse.java | 6 +- .../storage/queue/models/PeekedMessage.java | 169 ++++++++++++++++++ .../storage/queue/models/package-info.java | 2 +- storage/client/queue/swagger/queue.json | 4 +- 29 files changed, 273 insertions(+), 152 deletions(-) rename storage/client/blob/src/main/java/com/azure/storage/blob/implementation/{SignedIdentifiersWrapper.java => SignedIdentifierWrapper.java} (63%) create mode 100644 storage/client/queue/src/main/java/com/azure/storage/queue/models/PeekedMessage.java diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerAsyncClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerAsyncClient.java index 406a7440b0c5b..726876c488060 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerAsyncClient.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerAsyncClient.java @@ -613,7 +613,7 @@ private Flux listBlobsHierarchyHelper(String delimiter, ListBlobsOptio } else { prefixes = Flux.empty(); } - Flux result = blobs.concatWith(prefixes.map(prefix -> new BlobItem().name(prefix.name()).isPrefix(true))); + Flux result = blobs.map(item -> item.isPrefix(false)).concatWith(prefixes.map(prefix -> new BlobItem().name(prefix.name()).isPrefix(true))); if (response.value().nextMarker() != null) { // Recursively add the continuation items to the observable. diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/AppendBlobsImpl.java b/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/AppendBlobsImpl.java index 2763bb76a36d3..11c3c65f677de 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/AppendBlobsImpl.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/AppendBlobsImpl.java @@ -63,11 +63,11 @@ public AppendBlobsImpl(AzureBlobStorageImpl client) { } /** - * The interface defining all the services for AppendBlobs to be used by - * the proxy service to perform REST calls. + * The interface defining all the services for AzureBlobStorageAppendBlobs + * to be used by the proxy service to perform REST calls. */ @Host("{url}") - @ServiceInterface(name = "AppendBlobs") + @ServiceInterface(name = "AzureBlobStorageAppendBlobs") private interface AppendBlobsService { @Put("{containerName}/{blob}") @ExpectedResponses({201}) @@ -80,7 +80,7 @@ private interface AppendBlobsService { Mono appendBlock(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @BodyParam("application/octet-stream") Flux body, @QueryParam("timeout") Integer timeout, @HeaderParam("Content-Length") long contentLength, @HeaderParam("Content-MD5") String transactionalContentMD5, @QueryParam("x-ms-encryption-key") String encryptionKey, @QueryParam("x-ms-encryption-key-sha256") String encryptionKeySha256, @QueryParam("x-ms-encryption-algorithm") EncryptionAlgorithmType encryptionAlgorithm, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("x-ms-blob-condition-maxsize") Long maxSize, @HeaderParam("x-ms-blob-condition-appendpos") Long appendPosition, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, Context context); @Put("{containerName}/{blob}") - @ExpectedResponses({201, 304}) + @ExpectedResponses({201}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono appendBlockFromUrl(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @HeaderParam("x-ms-copy-source") URL copySource, @HeaderParam("x-ms-source-range") String sourceRange, @HeaderParam("x-ms-source-content-md5") String sourceContentMD5, @QueryParam("timeout") Integer timeout, @HeaderParam("Content-Length") long contentLength, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("x-ms-blob-condition-maxsize") Long maxSize, @HeaderParam("x-ms-blob-condition-appendpos") Long appendPosition, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, @HeaderParam("x-ms-source-if-modified-since") DateTimeRfc1123 sourceIfModifiedSince, @HeaderParam("x-ms-source-if-unmodified-since") DateTimeRfc1123 sourceIfUnmodifiedSince, @HeaderParam("x-ms-source-if-match") String sourceIfMatch, @HeaderParam("x-ms-source-if-none-match") String sourceIfNoneMatch, Context context); } diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/BlobsImpl.java b/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/BlobsImpl.java index 71311863df22e..72c54749e01ad 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/BlobsImpl.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/BlobsImpl.java @@ -78,19 +78,19 @@ public BlobsImpl(AzureBlobStorageImpl client) { } /** - * The interface defining all the services for Blobs to be used by the - * proxy service to perform REST calls. + * The interface defining all the services for AzureBlobStorageBlobs to be + * used by the proxy service to perform REST calls. */ @Host("{url}") - @ServiceInterface(name = "Blobs") + @ServiceInterface(name = "AzureBlobStorageBlobs") private interface BlobsService { @Get("{containerName}/{blob}") - @ExpectedResponses({200, 206, 304}) + @ExpectedResponses({200, 206}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono download(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @QueryParam("snapshot") String snapshot, @QueryParam("versionid") String versionId, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-range") String range, @HeaderParam("x-ms-range-get-content-md5") Boolean rangeGetContentMD5, @QueryParam("x-ms-encryption-key") String encryptionKey, @QueryParam("x-ms-encryption-key-sha256") String encryptionKeySha256, @QueryParam("x-ms-encryption-algorithm") EncryptionAlgorithmType encryptionAlgorithm, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, Context context); @Head("{containerName}/{blob}") - @ExpectedResponses({200, 304}) + @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono getProperties(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @QueryParam("snapshot") String snapshot, @QueryParam("versionid") String versionId, @QueryParam("timeout") Integer timeout, @QueryParam("x-ms-encryption-key") String encryptionKey, @QueryParam("x-ms-encryption-key-sha256") String encryptionKeySha256, @QueryParam("x-ms-encryption-algorithm") EncryptionAlgorithmType encryptionAlgorithm, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, Context context); diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/BlockBlobsImpl.java b/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/BlockBlobsImpl.java index 07f3f4f15061b..bbd1f64dfec4d 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/BlockBlobsImpl.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/BlockBlobsImpl.java @@ -67,11 +67,11 @@ public BlockBlobsImpl(AzureBlobStorageImpl client) { } /** - * The interface defining all the services for BlockBlobs to be used by the - * proxy service to perform REST calls. + * The interface defining all the services for AzureBlobStorageBlockBlobs + * to be used by the proxy service to perform REST calls. */ @Host("{url}") - @ServiceInterface(name = "BlockBlobs") + @ServiceInterface(name = "AzureBlobStorageBlockBlobs") private interface BlockBlobsService { @Put("{containerName}/{blob}") @ExpectedResponses({201}) @@ -84,7 +84,7 @@ private interface BlockBlobsService { Mono stageBlock(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @QueryParam("blockid") String blockId, @HeaderParam("Content-Length") long contentLength, @HeaderParam("Content-MD5") String transactionalContentMD5, @BodyParam("application/octet-stream") Flux body, @QueryParam("timeout") Integer timeout, @QueryParam("x-ms-encryption-key") String encryptionKey, @QueryParam("x-ms-encryption-key-sha256") String encryptionKeySha256, @QueryParam("x-ms-encryption-algorithm") EncryptionAlgorithmType encryptionAlgorithm, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @HeaderParam("x-ms-lease-id") String leaseId, Context context); @Put("{containerName}/{blob}") - @ExpectedResponses({201, 304}) + @ExpectedResponses({201}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono stageBlockFromURL(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @QueryParam("blockid") String blockId, @HeaderParam("Content-Length") long contentLength, @HeaderParam("x-ms-copy-source") URL copySource, @HeaderParam("x-ms-source-range") String sourceRange, @HeaderParam("x-ms-source-content-md5") String sourceContentMD5, @QueryParam("timeout") Integer timeout, @QueryParam("x-ms-encryption-key") String encryptionKey, @QueryParam("x-ms-encryption-key-sha256") String encryptionKeySha256, @QueryParam("x-ms-encryption-algorithm") EncryptionAlgorithmType encryptionAlgorithm, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("x-ms-source-if-modified-since") DateTimeRfc1123 sourceIfModifiedSince, @HeaderParam("x-ms-source-if-unmodified-since") DateTimeRfc1123 sourceIfUnmodifiedSince, @HeaderParam("x-ms-source-if-match") String sourceIfMatch, @HeaderParam("x-ms-source-if-none-match") String sourceIfNoneMatch, Context context); diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/ContainersImpl.java b/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/ContainersImpl.java index 6070cff261a33..1ed84f595d577 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/ContainersImpl.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/ContainersImpl.java @@ -43,11 +43,10 @@ import com.azure.storage.blob.models.PublicAccessType; import com.azure.storage.blob.models.SignedIdentifier; import com.azure.storage.blob.models.StorageErrorException; -import reactor.core.publisher.Mono; - import java.time.OffsetDateTime; import java.util.List; import java.util.Map; +import reactor.core.publisher.Mono; /** * An instance of this class provides access to all the operations defined in @@ -75,11 +74,11 @@ public ContainersImpl(AzureBlobStorageImpl client) { } /** - * The interface defining all the services for Containers to be used by the - * proxy service to perform REST calls. + * The interface defining all the services for AzureBlobStorageContainers + * to be used by the proxy service to perform REST calls. */ @Host("{url}") - @ServiceInterface(name = "Containers") + @ServiceInterface(name = "AzureBlobStorageContainers") private interface ContainersService { @Put("{containerName}") @ExpectedResponses({201}) @@ -109,7 +108,7 @@ private interface ContainersService { @Put("{containerName}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono setAccessPolicy(@PathParam("containerName") String containerName, @HostParam("url") String url, @BodyParam("application/xml; charset=utf-8") SignedIdentifiersWrapper containerAcl, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-blob-public-access") PublicAccessType access, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("restype") String restype, @QueryParam("comp") String comp, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, Context context); + Mono setAccessPolicy(@PathParam("containerName") String containerName, @HostParam("url") String url, @BodyParam("application/xml; charset=utf-8") SignedIdentifierWrapper containerAcl, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-blob-public-access") PublicAccessType access, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("restype") String restype, @QueryParam("comp") String comp, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, Context context); @Put("{containerName}") @ExpectedResponses({201}) @@ -382,7 +381,7 @@ public Mono setAccessPolicyWithRestResponseAs final String restype = "container"; final String comp = "acl"; final String leaseId = null; - SignedIdentifiersWrapper containerAclConverted = new SignedIdentifiersWrapper(null); + SignedIdentifierWrapper containerAclConverted = new SignedIdentifierWrapper(null); DateTimeRfc1123 ifModifiedSinceConverted = null; DateTimeRfc1123 ifUnmodifiedSinceConverted = null; return service.setAccessPolicy(containerName, this.client.url(), containerAclConverted, timeout, access, this.client.version(), requestId, restype, comp, leaseId, ifModifiedSinceConverted, ifUnmodifiedSinceConverted, context); @@ -418,7 +417,7 @@ public Mono setAccessPolicyWithRestResponseAs if (modifiedAccessConditions != null) { ifUnmodifiedSince = modifiedAccessConditions.ifUnmodifiedSince(); } - SignedIdentifiersWrapper containerAclConverted = new SignedIdentifiersWrapper(containerAcl); + SignedIdentifierWrapper containerAclConverted = new SignedIdentifierWrapper(containerAcl); DateTimeRfc1123 ifModifiedSinceConverted = ifModifiedSince == null ? null : new DateTimeRfc1123(ifModifiedSince); DateTimeRfc1123 ifUnmodifiedSinceConverted = ifUnmodifiedSince == null ? null : new DateTimeRfc1123(ifUnmodifiedSince); return service.setAccessPolicy(containerName, this.client.url(), containerAclConverted, timeout, access, this.client.version(), requestId, restype, comp, leaseId, ifModifiedSinceConverted, ifUnmodifiedSinceConverted, context); diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/PageBlobsImpl.java b/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/PageBlobsImpl.java index 2f851914b9067..24da9f9558963 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/PageBlobsImpl.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/PageBlobsImpl.java @@ -71,11 +71,11 @@ public PageBlobsImpl(AzureBlobStorageImpl client) { } /** - * The interface defining all the services for PageBlobs to be used by the - * proxy service to perform REST calls. + * The interface defining all the services for AzureBlobStoragePageBlobs to + * be used by the proxy service to perform REST calls. */ @Host("{url}") - @ServiceInterface(name = "PageBlobs") + @ServiceInterface(name = "AzureBlobStoragePageBlobs") private interface PageBlobsService { @Put("{containerName}/{blob}") @ExpectedResponses({201}) @@ -93,17 +93,17 @@ private interface PageBlobsService { Mono clearPages(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @HeaderParam("Content-Length") long contentLength, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-range") String range, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @HeaderParam("x-ms-page-write") String pageWrite, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("x-ms-if-sequence-number-le") Long ifSequenceNumberLessThanOrEqualTo, @HeaderParam("x-ms-if-sequence-number-lt") Long ifSequenceNumberLessThan, @HeaderParam("x-ms-if-sequence-number-eq") Long ifSequenceNumberEqualTo, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, Context context); @Put("{containerName}/{blob}") - @ExpectedResponses({201, 304}) + @ExpectedResponses({201}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono uploadPagesFromURL(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @HeaderParam("x-ms-copy-source") URL copySource, @HeaderParam("x-ms-source-range") String sourceRange, @HeaderParam("x-ms-source-content-md5") String sourceContentMD5, @HeaderParam("Content-Length") long contentLength, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-range") String range, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @HeaderParam("x-ms-page-write") String pageWrite, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("x-ms-if-sequence-number-le") Long ifSequenceNumberLessThanOrEqualTo, @HeaderParam("x-ms-if-sequence-number-lt") Long ifSequenceNumberLessThan, @HeaderParam("x-ms-if-sequence-number-eq") Long ifSequenceNumberEqualTo, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, @HeaderParam("x-ms-source-if-modified-since") DateTimeRfc1123 sourceIfModifiedSince, @HeaderParam("x-ms-source-if-unmodified-since") DateTimeRfc1123 sourceIfUnmodifiedSince, @HeaderParam("x-ms-source-if-match") String sourceIfMatch, @HeaderParam("x-ms-source-if-none-match") String sourceIfNoneMatch, Context context); @Get("{containerName}/{blob}") - @ExpectedResponses({200, 304}) + @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono getPageRanges(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @QueryParam("snapshot") String snapshot, @QueryParam("versionid") String versionId, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-range") String range, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, Context context); @Get("{containerName}/{blob}") - @ExpectedResponses({200, 304}) + @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) Mono getPageRangesDiff(@PathParam("containerName") String containerName, @PathParam("blob") String blob, @HostParam("url") String url, @QueryParam("snapshot") String snapshot, @QueryParam("versionid") String versionId, @QueryParam("timeout") Integer timeout, @QueryParam("prevsnapshot") String prevsnapshot, @HeaderParam("x-ms-range") String range, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, @HeaderParam("x-ms-lease-id") String leaseId, @HeaderParam("If-Modified-Since") DateTimeRfc1123 ifModifiedSince, @HeaderParam("If-Unmodified-Since") DateTimeRfc1123 ifUnmodifiedSince, @HeaderParam("If-Match") String ifMatch, @HeaderParam("If-None-Match") String ifNoneMatch, Context context); diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/ServicesImpl.java b/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/ServicesImpl.java index 1720197cee69c..09808f42733e4 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/ServicesImpl.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/ServicesImpl.java @@ -57,11 +57,11 @@ public ServicesImpl(AzureBlobStorageImpl client) { } /** - * The interface defining all the services for Services to be used by the - * proxy service to perform REST calls. + * The interface defining all the services for AzureBlobStorageServices to + * be used by the proxy service to perform REST calls. */ @Host("{url}") - @ServiceInterface(name = "Services") + @ServiceInterface(name = "AzureBlobStorageServices") private interface ServicesService { @Put("") @ExpectedResponses({202}) diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/SignedIdentifiersWrapper.java b/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/SignedIdentifierWrapper.java similarity index 63% rename from storage/client/blob/src/main/java/com/azure/storage/blob/implementation/SignedIdentifiersWrapper.java rename to storage/client/blob/src/main/java/com/azure/storage/blob/implementation/SignedIdentifierWrapper.java index f431e1fe84a19..8ad4982f32207 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/SignedIdentifiersWrapper.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/SignedIdentifierWrapper.java @@ -14,19 +14,19 @@ /** * A wrapper around List<SignedIdentifier> which provides top-level metadata for serialization. */ -@JacksonXmlRootElement(localName = "SignedIdentifiers") -public final class SignedIdentifiersWrapper { - @JacksonXmlProperty(localName = "SignedIdentifiers") - private final List signedIdentifiers; +@JacksonXmlRootElement(localName = "SignedIdentifier") +public final class SignedIdentifierWrapper { + @JacksonXmlProperty(localName = "SignedIdentifier") + private final List signedIdentifier; /** - * Creates an instance of SignedIdentifiersWrapper. + * Creates an instance of SignedIdentifierWrapper. * - * @param signedIdentifiers the list. + * @param signedIdentifier the list. */ @JsonCreator - public SignedIdentifiersWrapper(@JsonProperty("SignedIdentifiers") List signedIdentifiers) { - this.signedIdentifiers = signedIdentifiers; + public SignedIdentifierWrapper(@JsonProperty("SignedIdentifier") List signedIdentifier) { + this.signedIdentifier = signedIdentifier; } /** @@ -35,6 +35,6 @@ public SignedIdentifiersWrapper(@JsonProperty("SignedIdentifiers") List items() { - return signedIdentifiers; + return signedIdentifier; } } diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/package-info.java b/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/package-info.java index 5f341b8ad1be0..dcf10679cc979 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/package-info.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/implementation/package-info.java @@ -3,7 +3,7 @@ // Code generated by Microsoft (R) AutoRest Code Generator. /** - * This package contains the implementations and inner classes for + * Package containing the implementations and inner classes for * AzureBlobStorage. */ package com.azure.storage.blob.implementation; diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobHierarchyListSegment.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobHierarchyListSegment.java index d90e89ab602f3..d9eb4ef87da8f 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobHierarchyListSegment.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobHierarchyListSegment.java @@ -6,6 +6,7 @@ import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.util.ArrayList; import java.util.List; @@ -15,6 +16,7 @@ */ @JacksonXmlRootElement(localName = "Blobs") @Fluent +@JsonDeserialize(using = CustomHierarchicalListingDeserializer.class) public final class BlobHierarchyListSegment { /* * The blobPrefixes property. diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobItem.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobItem.java index eb73dd3366b67..3d777a4b2e386 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobItem.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/BlobItem.java @@ -4,15 +4,16 @@ package com.azure.storage.blob.models; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; - import java.util.Map; /** * An Azure Storage blob. */ @JacksonXmlRootElement(localName = "Blob") +@Fluent public final class BlobItem { /* * The name property. @@ -50,7 +51,11 @@ public final class BlobItem { @JsonProperty(value = "Metadata") private Map metadata; - private boolean isPrefix = false; + /* + * The isPrefix property. + */ + @JsonProperty(value = "IsPrefix") + private Boolean isPrefix; /** * Get the name property: The name property. @@ -173,18 +178,21 @@ public BlobItem metadata(Map metadata) { } /** - * @return if the blob item is a prefix instead of an actual blob. + * Get the isPrefix property: The isPrefix property. + * + * @return the isPrefix value. */ - public boolean isPrefix() { - return isPrefix; + public Boolean isPrefix() { + return this.isPrefix; } /** - * Sets if the blob item is a prefix instead of an actual blob - * @param isPrefix if the item is a prefix - * @return the BlobItem object itself + * Set the isPrefix property: The isPrefix property. + * + * @param isPrefix the isPrefix value to set. + * @return the BlobItem object itself. */ - public BlobItem isPrefix(boolean isPrefix) { + public BlobItem isPrefix(Boolean isPrefix) { this.isPrefix = isPrefix; return this; } diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/models/package-info.java b/storage/client/blob/src/main/java/com/azure/storage/blob/models/package-info.java index 653e8a46d1d67..a078397789b87 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/models/package-info.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/models/package-info.java @@ -3,6 +3,6 @@ // Code generated by Microsoft (R) AutoRest Code Generator. /** - * This package contains the data models for AzureBlobStorage. + * Package containing the data models for AzureBlobStorage. */ package com.azure.storage.blob.models; diff --git a/storage/client/blob/src/test/java/com/azure/storage/blob/APISpec.groovy b/storage/client/blob/src/test/java/com/azure/storage/blob/APISpec.groovy index c59095e5f66c6..c0a23c7b74540 100644 --- a/storage/client/blob/src/test/java/com/azure/storage/blob/APISpec.groovy +++ b/storage/client/blob/src/test/java/com/azure/storage/blob/APISpec.groovy @@ -54,7 +54,7 @@ class APISpec extends Specification { static defaultDataSize = defaultData.remaining() // If debugging is enabled, recordings cannot run as there can only be one proxy at a time. - static boolean enableDebugging = false + static boolean enableDebugging = true // Prefixes for blobs and containers static String containerPrefix = "jtc" // java test container diff --git a/storage/client/blob/swagger/blob.json b/storage/client/blob/swagger/blob.json index 4a89d47458cc3..19d7f37b25a65 100644 --- a/storage/client/blob/swagger/blob.json +++ b/storage/client/blob/swagger/blob.json @@ -2405,15 +2405,6 @@ "format": "file" } }, - "304": { - "description": "The condition specified using HTTP conditional header(s) is not met.", - "headers": { - "x-ms-error-code": { - "x-ms-client-name": "ErrorCode", - "type": "string" - } - } - }, "default": { "description": "Failure", "headers": { @@ -2706,15 +2697,6 @@ } } }, - "304": { - "description": "The condition specified using HTTP conditional header(s) is not met.", - "headers": { - "x-ms-error-code": { - "x-ms-client-name": "ErrorCode", - "type": "string" - } - } - }, "default": { "description": "Failure", "headers": { @@ -5077,15 +5059,6 @@ } } }, - "304": { - "description": "The condition specified using HTTP conditional header(s) is not met.", - "headers": { - "x-ms-error-code": { - "x-ms-client-name": "ErrorCode", - "type": "string" - } - } - }, "default": { "description": "Failure", "headers": { @@ -5791,15 +5764,6 @@ } } }, - "304": { - "description": "The condition specified using HTTP conditional header(s) is not met.", - "headers": { - "x-ms-error-code": { - "x-ms-client-name": "ErrorCode", - "type": "string" - } - } - }, "default": { "description": "Failure", "headers": { @@ -5930,15 +5894,6 @@ "$ref": "#/definitions/PageList" } }, - "304": { - "description": "The condition specified using HTTP conditional header(s) is not met.", - "headers": { - "x-ms-error-code": { - "x-ms-client-name": "ErrorCode", - "type": "string" - } - } - }, "default": { "description": "Failure", "headers": { @@ -6056,15 +6011,6 @@ "$ref": "#/definitions/PageList" } }, - "304": { - "description": "The condition specified using HTTP conditional header(s) is not met.", - "headers": { - "x-ms-error-code": { - "x-ms-client-name": "ErrorCode", - "type": "string" - } - } - }, "default": { "description": "Failure", "headers": { @@ -6683,15 +6629,6 @@ } } }, - "304": { - "description": "The condition specified using HTTP conditional header(s) is not met.", - "headers": { - "x-ms-error-code": { - "x-ms-client-name": "ErrorCode", - "type": "string" - } - } - }, "default": { "description": "Failure", "headers": { @@ -6939,7 +6876,13 @@ "$ref": "#/definitions/BlobProperties" }, "Metadata": { - "$ref": "#/definitions/BlobMetadata" + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "IsPrefix": { + "type": "boolean" } } }, @@ -7767,7 +7710,7 @@ }, "xml": { "wrapped": true, - "name": "SignedIdentifiers" + "name": "SignedIdentifier" } }, "StaticWebsite": { @@ -7864,7 +7807,7 @@ "pattern": "^[a-zA-Z0-9]+(?:/[a-zA-Z0-9]+)*(?:\\.[a-zA-Z0-9]+){0,1}$", "minLength": 1, "maxLength": 1024, - "x-ms-parameter-location": "client", + "x-ms-parameter-location": "method", "description": "The blob name." }, "BlobCacheControl": { @@ -8119,7 +8062,7 @@ "in": "path", "required": true, "type": "string", - "x-ms-parameter-location": "client", + "x-ms-parameter-location": "method", "description": "The container name." }, "ContentCrc64": { 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 a7a40bc0007e6..b7cedcaad9b81 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 @@ -55,11 +55,11 @@ public DirectorysImpl(AzureFileStorageImpl client) { } /** - * The interface defining all the services for Directorys to be used by the - * proxy service to perform REST calls. + * The interface defining all the services for AzureFileStorageDirectorys + * to be used by the proxy service to perform REST calls. */ @Host("{url}") - @ServiceInterface(name = "Directorys") + @ServiceInterface(name = "AzureFileStorageDirectorys") private interface DirectorysService { @Put("{shareName}/{directory}") @ExpectedResponses({201}) 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 fde67800343f7..b8f344dba8f82 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 @@ -67,11 +67,11 @@ public FilesImpl(AzureFileStorageImpl client) { } /** - * The interface defining all the services for Files to be used by the - * proxy service to perform REST calls. + * The interface defining all the services for AzureFileStorageFiles to be + * used by the proxy service to perform REST calls. */ @Host("{url}") - @ServiceInterface(name = "Files") + @ServiceInterface(name = "AzureFileStorageFiles") private interface FilesService { @Put("{shareName}/{directory}/{fileName}") @ExpectedResponses({201}) 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 993bbad2b93b4..b83b5490bc131 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 @@ -55,11 +55,11 @@ public ServicesImpl(AzureFileStorageImpl client) { } /** - * The interface defining all the services for Services to be used by the - * proxy service to perform REST calls. + * The interface defining all the services for AzureFileStorageServices to + * be used by the proxy service to perform REST calls. */ @Host("{url}") - @ServiceInterface(name = "Services") + @ServiceInterface(name = "AzureFileStorageServices") private interface ServicesService { @Put("") @ExpectedResponses({202}) 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 83466fe45e31e..a0a3758a23da6 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 @@ -61,11 +61,11 @@ public SharesImpl(AzureFileStorageImpl client) { } /** - * The interface defining all the services for Shares to be used by the - * proxy service to perform REST calls. + * The interface defining all the services for AzureFileStorageShares to be + * used by the proxy service to perform REST calls. */ @Host("{url}") - @ServiceInterface(name = "Shares") + @ServiceInterface(name = "AzureFileStorageShares") private interface SharesService { @Put("{shareName}") @ExpectedResponses({201}) diff --git a/storage/client/file/src/main/java/com/azure/storage/file/implementation/package-info.java b/storage/client/file/src/main/java/com/azure/storage/file/implementation/package-info.java index c7e9e946b39e4..3119c8175b9cb 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/implementation/package-info.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/implementation/package-info.java @@ -3,7 +3,7 @@ // Code generated by Microsoft (R) AutoRest Code Generator. /** - * This package contains the implementations and inner classes for + * Package containing the implementations and inner classes for * AzureFileStorage. */ package com.azure.storage.file.implementation; diff --git a/storage/client/file/src/main/java/com/azure/storage/file/models/package-info.java b/storage/client/file/src/main/java/com/azure/storage/file/models/package-info.java index b21cb828d0f54..43000927e5788 100644 --- a/storage/client/file/src/main/java/com/azure/storage/file/models/package-info.java +++ b/storage/client/file/src/main/java/com/azure/storage/file/models/package-info.java @@ -3,6 +3,6 @@ // Code generated by Microsoft (R) AutoRest Code Generator. /** - * This package contains the data models for AzureFileStorage. + * Package containing the data models for AzureFileStorage. */ package com.azure.storage.file.models; diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessageIdsImpl.java b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessageIdsImpl.java index 611e58170b3c8..1b95a0982419f 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessageIdsImpl.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessageIdsImpl.java @@ -50,11 +50,11 @@ public MessageIdsImpl(AzureQueueStorageImpl client) { } /** - * The interface defining all the services for MessageIds to be used by the - * proxy service to perform REST calls. + * The interface defining all the services for AzureQueueStorageMessageIds + * to be used by the proxy service to perform REST calls. */ @Host("{url}") - @ServiceInterface(name = "MessageIds") + @ServiceInterface(name = "AzureQueueStorageMessageIds") private interface MessageIdsService { @Put("{queueName}/messages/{messageid}") @ExpectedResponses({204}) diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessagesImpl.java b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessagesImpl.java index 32809752caebc..b7815e46867e4 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessagesImpl.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessagesImpl.java @@ -53,11 +53,11 @@ public MessagesImpl(AzureQueueStorageImpl client) { } /** - * The interface defining all the services for Messages to be used by the - * proxy service to perform REST calls. + * The interface defining all the services for AzureQueueStorageMessages to + * be used by the proxy service to perform REST calls. */ @Host("{url}") - @ServiceInterface(name = "Messages") + @ServiceInterface(name = "AzureQueueStorageMessages") private interface MessagesService { @Get("{queueName}/messages") @ExpectedResponses({200}) diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/QueuesImpl.java b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/QueuesImpl.java index 9665d355022b3..f498f6c4d3955 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/QueuesImpl.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/QueuesImpl.java @@ -57,11 +57,11 @@ public QueuesImpl(AzureQueueStorageImpl client) { } /** - * The interface defining all the services for Queues to be used by the - * proxy service to perform REST calls. + * The interface defining all the services for AzureQueueStorageQueues to + * be used by the proxy service to perform REST calls. */ @Host("{url}") - @ServiceInterface(name = "Queues") + @ServiceInterface(name = "AzureQueueStorageQueues") private interface QueuesService { @Put("{queueName}") @ExpectedResponses({201, 204}) diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/ServicesImpl.java b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/ServicesImpl.java index 32fc830c6b168..c31fd62cd839e 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/ServicesImpl.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/ServicesImpl.java @@ -56,11 +56,11 @@ public ServicesImpl(AzureQueueStorageImpl client) { } /** - * The interface defining all the services for Services to be used by the - * proxy service to perform REST calls. + * The interface defining all the services for AzureQueueStorageServices to + * be used by the proxy service to perform REST calls. */ @Host("{url}") - @ServiceInterface(name = "Services") + @ServiceInterface(name = "AzureQueueStorageServices") private interface ServicesService { @Put("") @ExpectedResponses({202}) diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/package-info.java b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/package-info.java index 80e51df7f9675..324cc0b19dc2b 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/package-info.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/package-info.java @@ -3,7 +3,7 @@ // Code generated by Microsoft (R) AutoRest Code Generator. /** - * This package contains the implementations and inner classes for + * Package containing the implementations and inner classes for * AzureQueueStorage. */ package com.azure.storage.queue.implementation; diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesPeekResponse.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesPeekResponse.java index 8ca8ed06fd99c..27ac646138908 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesPeekResponse.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesPeekResponse.java @@ -12,7 +12,7 @@ /** * Contains all response data for the peek operation. */ -public final class MessagesPeekResponse extends ResponseBase> { +public final class MessagesPeekResponse extends ResponseBase> { /** * Creates an instance of MessagesPeekResponse. * @@ -22,7 +22,7 @@ public final class MessagesPeekResponse extends ResponseBase value, MessagesPeekHeaders headers) { + public MessagesPeekResponse(HttpRequest request, int statusCode, HttpHeaders rawHeaders, List value, MessagesPeekHeaders headers) { super(request, statusCode, rawHeaders, value, headers); } @@ -30,7 +30,7 @@ public MessagesPeekResponse(HttpRequest request, int statusCode, HttpHeaders raw * @return the deserialized response body. */ @Override - public List value() { + public List value() { return super.value(); } } diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/PeekedMessage.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/PeekedMessage.java new file mode 100644 index 0000000000000..c8a3c26ab9738 --- /dev/null +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/PeekedMessage.java @@ -0,0 +1,169 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// Code generated by Microsoft (R) AutoRest Code Generator. + +package com.azure.storage.queue.models; + +import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; +import java.time.OffsetDateTime; + +/** + * The object returned in the QueueMessageList array when calling Peek Messages + * on a Queue. + */ +@JacksonXmlRootElement(localName = "QueueMessage") +@Fluent +public final class PeekedMessage { + /* + * The Id of the Message. + */ + @JsonProperty(value = "MessageId", required = true) + private String messageId; + + /* + * The time the Message was inserted into the Queue. + */ + @JsonProperty(value = "InsertionTime", required = true) + private DateTimeRfc1123 insertionTime; + + /* + * The time that the Message will expire and be automatically deleted. + */ + @JsonProperty(value = "ExpirationTime", required = true) + private DateTimeRfc1123 expirationTime; + + /* + * The number of times the message has been dequeued. + */ + @JsonProperty(value = "DequeueCount", required = true) + private long dequeueCount; + + /* + * The content of the Message. + */ + @JsonProperty(value = "MessageText", required = true) + private String messageText; + + /** + * Get the messageId property: The Id of the Message. + * + * @return the messageId value. + */ + public String messageId() { + return this.messageId; + } + + /** + * Set the messageId property: The Id of the Message. + * + * @param messageId the messageId value to set. + * @return the PeekedMessage object itself. + */ + public PeekedMessage messageId(String messageId) { + this.messageId = messageId; + return this; + } + + /** + * Get the insertionTime property: The time the Message was inserted into + * the Queue. + * + * @return the insertionTime value. + */ + public OffsetDateTime insertionTime() { + if (this.insertionTime == null) { + return null; + } + return this.insertionTime.dateTime(); + } + + /** + * Set the insertionTime property: The time the Message was inserted into + * the Queue. + * + * @param insertionTime the insertionTime value to set. + * @return the PeekedMessage object itself. + */ + public PeekedMessage insertionTime(OffsetDateTime insertionTime) { + if (insertionTime == null) { + this.insertionTime = null; + } else { + this.insertionTime = new DateTimeRfc1123(insertionTime); + } + return this; + } + + /** + * Get the expirationTime property: The time that the Message will expire + * and be automatically deleted. + * + * @return the expirationTime value. + */ + public OffsetDateTime expirationTime() { + if (this.expirationTime == null) { + return null; + } + return this.expirationTime.dateTime(); + } + + /** + * Set the expirationTime property: The time that the Message will expire + * and be automatically deleted. + * + * @param expirationTime the expirationTime value to set. + * @return the PeekedMessage object itself. + */ + public PeekedMessage expirationTime(OffsetDateTime expirationTime) { + if (expirationTime == null) { + this.expirationTime = null; + } else { + this.expirationTime = new DateTimeRfc1123(expirationTime); + } + return this; + } + + /** + * Get the dequeueCount property: The number of times the message has been + * dequeued. + * + * @return the dequeueCount value. + */ + public long dequeueCount() { + return this.dequeueCount; + } + + /** + * Set the dequeueCount property: The number of times the message has been + * dequeued. + * + * @param dequeueCount the dequeueCount value to set. + * @return the PeekedMessage object itself. + */ + public PeekedMessage dequeueCount(long dequeueCount) { + this.dequeueCount = dequeueCount; + return this; + } + + /** + * Get the messageText property: The content of the Message. + * + * @return the messageText value. + */ + public String messageText() { + return this.messageText; + } + + /** + * Set the messageText property: The content of the Message. + * + * @param messageText the messageText value to set. + * @return the PeekedMessage object itself. + */ + public PeekedMessage messageText(String messageText) { + this.messageText = messageText; + return this; + } +} diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/package-info.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/package-info.java index 92606a7993c12..3444962847a80 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/package-info.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/package-info.java @@ -3,6 +3,6 @@ // Code generated by Microsoft (R) AutoRest Code Generator. /** - * This package contains the data models for AzureQueueStorage. + * Package containing the data models for AzureQueueStorage. */ package com.azure.storage.queue.models; diff --git a/storage/client/queue/swagger/queue.json b/storage/client/queue/swagger/queue.json index 06155a07afed3..ae21a6d87bed0 100644 --- a/storage/client/queue/swagger/queue.json +++ b/storage/client/queue/swagger/queue.json @@ -1432,7 +1432,7 @@ "name": "QueueMessage" } }, - "PeekedMessageItem": { + "PeekedMessage": { "description": "The object returned in the QueueMessageList array when calling Peek Messages on a Queue", "type": "object", "required": [ @@ -1530,7 +1530,7 @@ "description": "The object returned when calling Peek Messages on a Queue", "type": "array", "items": { - "$ref": "#/definitions/PeekedMessageItem", + "$ref": "#/definitions/PeekedMessage", "xml": { "name": "QueueMessage" } From 44fb56eadbd40b68bb724a5c3c977356f3f96ea1 Mon Sep 17 00:00:00 2001 From: Sima Zhu <48036328+sima-zhu@users.noreply.github.com> Date: Tue, 23 Jul 2019 17:49:20 -0700 Subject: [PATCH 08/17] Initial checkin for Storage file (#4414) * Finished the restructure, refactor builder. Added sleep in record feature. Linting --- .../resources/spotbugs/spotbugs-exclude.xml | 1 + eng/spotbugs-aggregate-report/pom.xml | 7 + pom.client.xml | 5 + .../secrets/KeyVaultErrorCodeStrings.java | 1 - .../src/samples/java/FileTransferExample.java | 5 +- storage/client/file/README.md | 478 +++++++++++ storage/client/file/pom.xml | 75 ++ .../credentials/SharedKeyCredential.java | 43 +- .../common/exception/StorageException.java | 51 ++ .../common/policy/RequestRetryOptions.java | 5 + .../common/policy/RequestRetryPolicy.java | 5 + .../storage/file/DirectoryAsyncClient.java | 469 ++++++++++- .../azure/storage/file/DirectoryClient.java | 353 +++++++- .../storage/file/DirectoryClientBuilder.java | 352 +++++++- .../azure/storage/file/FileAsyncClient.java | 707 +++++++++++++++- .../com/azure/storage/file/FileClient.java | 432 +++++++++- .../azure/storage/file/FileClientBuilder.java | 356 +++++++- .../azure/storage/file/FileConfiguration.java | 13 + .../storage/file/FileServiceAsyncClient.java | 314 ++++++- .../azure/storage/file/FileServiceClient.java | 236 +++++- .../file/FileServiceClientBuilder.java | 306 ++++++- .../azure/storage/file/ShareAsyncClient.java | 407 ++++++++- .../com/azure/storage/file/ShareClient.java | 339 +++++++- .../storage/file/ShareClientBuilder.java | 338 +++++++- .../AzureFileStorageBuilder.java | 6 +- .../file/implementation/DirectorysImpl.java | 158 +++- .../file/implementation/FilesImpl.java | 198 +++-- .../file/implementation/ServicesImpl.java | 21 +- .../file/implementation/SharesImpl.java | 114 +-- .../models/DeleteSnapshotsOptionType.java | 7 +- .../storage/file/models/DirectoryInfo.java | 32 + .../file/models/DirectoryProperties.java | 53 ++ .../file/models/DirectorySetMetadataInfo.java | 34 + .../storage/file/models/FileCopyInfo.java | 58 ++ .../file/models/FileDownloadHeaders.java | 7 +- .../storage/file/models/FileDownloadInfo.java | 85 ++ .../file/models/FileGetPropertiesHeaders.java | 5 +- .../storage/file/models/FileHTTPHeaders.java | 5 +- .../azure/storage/file/models/FileInfo.java | 42 + .../storage/file/models/FileMetadataInfo.java | 22 + .../storage/file/models/FileProperties.java | 195 +++++ .../azure/storage/file/models/FileRange.java | 47 ++ .../azure/storage/file/models/FileRef.java | 42 + .../file/models/FileServiceProperties.java | 108 +++ .../storage/file/models/FileUploadInfo.java | 30 + .../file/models/FileUploadRangeHeaders.java | 5 +- ...istFilesAndDirectoriesSegmentResponse.java | 10 +- .../file/models/ListSharesOptions.java | 102 +++ .../models/ServicesGetPropertiesResponse.java | 6 +- .../azure/storage/file/models/ShareInfo.java | 32 + .../storage/file/models/ShareProperties.java | 15 + .../file/models/ShareSnapshotInfo.java | 46 +- .../storage/file/models/ShareStatistics.java | 20 + .../java/com/azure/file/AsyncSample.java | 67 ++ .../java/com/azure/file/DirectorySample.java | 115 +++ .../java/com/azure/file/FileSample.java | 144 ++++ .../com/azure/file/FileServiceSample.java | 67 ++ .../java/com/azure/file/ShareSample.java | 134 +++ .../file/DirectoryJavaDocCodeSamples.java | 586 +++++++++++++ .../storage/file/FileJavaDocCodeSamples.java | 785 ++++++++++++++++++ .../file/FileServiceJavaDocCodeSamples.java | 423 ++++++++++ .../storage/file/ShareJavaDocCodeSamples.java | 580 +++++++++++++ .../file/DirectoryAsyncClientTests.java | 321 +++++++ .../storage/file/DirectoryClientTestBase.java | 113 +++ .../storage/file/DirectoryClientTests.java | 259 ++++++ .../storage/file/FileAsyncClientTest.java | 215 +++++ .../azure/storage/file/FileClientTest.java | 202 +++++ .../storage/file/FileClientTestBase.java | 81 ++ .../file/FileServiceClientAsyncTests.java | 472 +++++++++++ .../file/FileServiceClientTestBase.java | 121 +++ .../storage/file/FileServiceClientTests.java | 479 +++++++++++ .../azure/storage/file/FileTestHelpers.java | 257 ++++++ .../com/azure/storage/file/LargeFileTest.java | 129 +++ .../storage/file/ShareAsyncClientTests.java | 618 ++++++++++++++ .../storage/file/ShareClientTestBase.java | 170 ++++ .../azure/storage/file/ShareClientTests.java | 490 +++++++++++ .../resources/session-records/abortCopy.json | 4 + .../clearMetadataFromDirClient.json | 42 + ...DirectoryAlreadyExistsFromShareClient.json | 76 ++ .../createDirectoryFromShareClient.json | 57 ++ ...teDirectoryInvalidNameFromShareClient.json | 57 ++ .../createExcessMaxSizeFromFileClient.json | 45 + .../createFileFromDirClient.json | 42 + ...eateFileWithoutCreateDirFromDirClient.json | 23 + .../session-records/createFromFileClient.json | 45 + .../createFromShareClient.json | 38 + .../createInvalidQuotaFromShareClient.json | 61 ++ .../createMinFromDirClient.json | 23 + .../session-records/createShare.json | 56 ++ .../createShareInvalidQuota.json | 60 ++ .../createShareTwiceDifferentMetadata.json | 75 ++ .../createShareTwiceSameMetadata.json | 75 ++ .../session-records/createSubDirectory.json | 42 + .../createSubDirectoryTwiceSameMetadata.json | 61 ++ .../createSubDirectoryWithMetadata.json | 42 + ...TwiceDifferentMetadataFromShareClient.json | 57 ++ .../createTwiceFromDirClient.json | 42 + ...reateTwiceSameMetadataFromShareClient.json | 57 ++ .../createWithMetadataFromDirClient.json | 23 + ...eDirectoryDoesNotExistFromShareClient.json | 57 ++ .../deleteDirectoryFromShareClient.json | 73 ++ .../deleteDoesNotExistFromShareClient.json | 42 + .../deleteFileFromDirClient.json | 58 ++ ...eteFileWithoutCreateFileFromDirClient.json | 42 + .../session-records/deleteFromDirClient.json | 39 + .../session-records/deleteFromFileClient.json | 39 + .../deleteFromShareClient.json | 57 ++ .../deleteNotExistFromDirClient.json | 23 + .../session-records/deleteShare.json | 56 ++ .../deleteShareDoesNotExist.json | 41 + .../deleteSnapshotFromShareClient.json | 95 +++ .../session-records/deleteSubDirectory.json | 58 ++ .../deleteThenCreateFromShareClient.json | 72 ++ ...eThenCreateShareFromFileServiceClient.json | 90 ++ ...eateShareTooSoonFromFileServiceClient.json | 75 ++ ...eleteThenCreateTooSoonFromShareClient.json | 76 ++ .../downloadWithProperties.json | 46 + .../forceCloseHandlesFromDirClient.json | 41 + .../forceCloseHandlesFromFileClient.json | 41 + .../getDirectoryDoesNotCreateADirectory.json | 57 ++ .../getFileClientFromDirClient.json | 4 + .../getHandlesFromDirClient.json | 4 + ...etMetadataDoesNotExistFromShareClient.json | 42 + .../getMetadataFromShareClient.json | 60 ++ .../session-records/getPolicies.json | 58 ++ .../getPoliciesDoesNotExist.json | 42 + ...PropertiesDoesNotExistFromShareClient.json | 42 + .../getPropertiesFromDirClient.json | 42 + .../getPropertiesFromFileClient.json | 45 + .../getPropertiesFromShareClient.json | 60 ++ ...tRootDirectoryDoesNotCreateADirectory.json | 57 ++ .../getShareDoesNotCreateAShare.json | 41 + .../session-records/getSnapshotId.json | 60 ++ ...otMetadataDoesNotExistFromShareClient.json | 57 ++ .../getSnapshotMetadataFromShareClient.json | 82 ++ .../getSnapshotPropertiesDoesNotExist.json | 57 ++ .../getSnapshotPropertiesFromShareClient.json | 82 ++ .../resources/session-records/getStats.json | 56 ++ .../session-records/getStatsDoesNotExist.json | 42 + .../getSubDirectoryClient.json | 4 + .../listFilesAndDirectoriesFromDirClient.json | 212 +++++ .../listHandlesFromFileClient.json | 41 + .../listRangesFromFileClient.json | 65 ++ .../resources/session-records/listShares.json | 142 ++++ .../listSharesIncludeMetadata.json | 142 ++++ ...listSharesIncludeMetadataAndSnapshots.json | 186 +++++ .../listSharesIncludeSnapshots.json | 186 +++++ .../listSharesInvalidMaxResults.json | 60 ++ .../session-records/listSharesWithLimit.json | 142 ++++ .../session-records/listSharesWithPrefix.json | 142 ++++ .../setFileServiceProperties.json | 110 +++ .../setHttpHeadersFromFileClient.json | 42 + .../setMeatadataFromFileClient.json | 42 + ...etMetadataDoesNotExistFromShareClient.json | 42 + .../setMetadataFromDirClient.json | 42 + .../setMetadataFromShareClient.json | 78 ++ .../setMetadataInvalidKeyFromDirClient.json | 42 + ...etadataInvalidMetadataFromShareClient.json | 57 ++ .../session-records/setPolicies.json | 77 ++ .../setPoliciesDoesNotExist.json | 43 + .../setPoliciesInvalidPermission.json | 58 ++ .../setPoliciesTooManyPermissions.json | 58 ++ ...PropertiesDoesNotExistFromShareClient.json | 42 + .../setPropertiesFromShareClient.json | 98 +++ .../setPropertiesInvalidAllowedHeader.json | 42 + .../setPropertiesInvalidAllowedMethod.json | 42 + .../setPropertiesInvalidAllowedOrigin.json | 42 + .../setPropertiesInvalidExposedHeader.json | 42 + ...PropertiesInvalidQuotaFromShareClient.json | 76 ++ .../setPropertiesTooManyRules.json | 42 + .../resources/session-records/snapshot.json | 60 ++ .../snapshotDifferentMetadata.json | 104 +++ .../session-records/snapshotDoesNotExist.json | 42 + .../session-records/snapshotSameMetadata.json | 82 ++ .../resources/session-records/startCopy.json | 43 + .../resources/session-records/upload.json | 44 + .../uploadToStorageAndDownloadToFile.json | 90 ++ .../session-records/urlFromDirClient.json | 4 + .../src/test/resources/testfiles/helloworld | 1 + storage/client/pom.xml | 123 +++ storage/client/queue/README.md | 8 +- 181 files changed, 19436 insertions(+), 449 deletions(-) create mode 100644 storage/client/file/README.md create mode 100644 storage/client/file/pom.xml create mode 100644 storage/client/file/src/main/java/com/azure/storage/common/exception/StorageException.java create mode 100644 storage/client/file/src/main/java/com/azure/storage/file/FileConfiguration.java create mode 100644 storage/client/file/src/main/java/com/azure/storage/file/models/DirectorySetMetadataInfo.java create mode 100644 storage/client/file/src/main/java/com/azure/storage/file/models/FileMetadataInfo.java create mode 100644 storage/client/file/src/main/java/com/azure/storage/file/models/FileRange.java create mode 100644 storage/client/file/src/samples/java/com/azure/file/AsyncSample.java create mode 100644 storage/client/file/src/samples/java/com/azure/file/DirectorySample.java create mode 100644 storage/client/file/src/samples/java/com/azure/file/FileSample.java create mode 100644 storage/client/file/src/samples/java/com/azure/file/FileServiceSample.java create mode 100644 storage/client/file/src/samples/java/com/azure/file/ShareSample.java create mode 100644 storage/client/file/src/samples/java/com/azure/storage/file/DirectoryJavaDocCodeSamples.java create mode 100644 storage/client/file/src/samples/java/com/azure/storage/file/FileJavaDocCodeSamples.java create mode 100644 storage/client/file/src/samples/java/com/azure/storage/file/FileServiceJavaDocCodeSamples.java create mode 100644 storage/client/file/src/samples/java/com/azure/storage/file/ShareJavaDocCodeSamples.java create mode 100644 storage/client/file/src/test/java/com/azure/storage/file/DirectoryAsyncClientTests.java create mode 100644 storage/client/file/src/test/java/com/azure/storage/file/DirectoryClientTestBase.java create mode 100644 storage/client/file/src/test/java/com/azure/storage/file/DirectoryClientTests.java create mode 100644 storage/client/file/src/test/java/com/azure/storage/file/FileAsyncClientTest.java create mode 100644 storage/client/file/src/test/java/com/azure/storage/file/FileClientTest.java create mode 100644 storage/client/file/src/test/java/com/azure/storage/file/FileClientTestBase.java create mode 100644 storage/client/file/src/test/java/com/azure/storage/file/FileServiceClientAsyncTests.java create mode 100644 storage/client/file/src/test/java/com/azure/storage/file/FileServiceClientTestBase.java create mode 100644 storage/client/file/src/test/java/com/azure/storage/file/FileServiceClientTests.java create mode 100644 storage/client/file/src/test/java/com/azure/storage/file/FileTestHelpers.java create mode 100644 storage/client/file/src/test/java/com/azure/storage/file/LargeFileTest.java create mode 100644 storage/client/file/src/test/java/com/azure/storage/file/ShareAsyncClientTests.java create mode 100644 storage/client/file/src/test/java/com/azure/storage/file/ShareClientTestBase.java create mode 100644 storage/client/file/src/test/java/com/azure/storage/file/ShareClientTests.java create mode 100644 storage/client/file/src/test/resources/session-records/abortCopy.json create mode 100644 storage/client/file/src/test/resources/session-records/clearMetadataFromDirClient.json create mode 100644 storage/client/file/src/test/resources/session-records/createDirectoryAlreadyExistsFromShareClient.json create mode 100644 storage/client/file/src/test/resources/session-records/createDirectoryFromShareClient.json create mode 100644 storage/client/file/src/test/resources/session-records/createDirectoryInvalidNameFromShareClient.json create mode 100644 storage/client/file/src/test/resources/session-records/createExcessMaxSizeFromFileClient.json create mode 100644 storage/client/file/src/test/resources/session-records/createFileFromDirClient.json create mode 100644 storage/client/file/src/test/resources/session-records/createFileWithoutCreateDirFromDirClient.json create mode 100644 storage/client/file/src/test/resources/session-records/createFromFileClient.json create mode 100644 storage/client/file/src/test/resources/session-records/createFromShareClient.json create mode 100644 storage/client/file/src/test/resources/session-records/createInvalidQuotaFromShareClient.json create mode 100644 storage/client/file/src/test/resources/session-records/createMinFromDirClient.json create mode 100644 storage/client/file/src/test/resources/session-records/createShare.json create mode 100644 storage/client/file/src/test/resources/session-records/createShareInvalidQuota.json create mode 100644 storage/client/file/src/test/resources/session-records/createShareTwiceDifferentMetadata.json create mode 100644 storage/client/file/src/test/resources/session-records/createShareTwiceSameMetadata.json create mode 100644 storage/client/file/src/test/resources/session-records/createSubDirectory.json create mode 100644 storage/client/file/src/test/resources/session-records/createSubDirectoryTwiceSameMetadata.json create mode 100644 storage/client/file/src/test/resources/session-records/createSubDirectoryWithMetadata.json create mode 100644 storage/client/file/src/test/resources/session-records/createTwiceDifferentMetadataFromShareClient.json create mode 100644 storage/client/file/src/test/resources/session-records/createTwiceFromDirClient.json create mode 100644 storage/client/file/src/test/resources/session-records/createTwiceSameMetadataFromShareClient.json create mode 100644 storage/client/file/src/test/resources/session-records/createWithMetadataFromDirClient.json create mode 100644 storage/client/file/src/test/resources/session-records/deleteDirectoryDoesNotExistFromShareClient.json create mode 100644 storage/client/file/src/test/resources/session-records/deleteDirectoryFromShareClient.json create mode 100644 storage/client/file/src/test/resources/session-records/deleteDoesNotExistFromShareClient.json create mode 100644 storage/client/file/src/test/resources/session-records/deleteFileFromDirClient.json create mode 100644 storage/client/file/src/test/resources/session-records/deleteFileWithoutCreateFileFromDirClient.json create mode 100644 storage/client/file/src/test/resources/session-records/deleteFromDirClient.json create mode 100644 storage/client/file/src/test/resources/session-records/deleteFromFileClient.json create mode 100644 storage/client/file/src/test/resources/session-records/deleteFromShareClient.json create mode 100644 storage/client/file/src/test/resources/session-records/deleteNotExistFromDirClient.json create mode 100644 storage/client/file/src/test/resources/session-records/deleteShare.json create mode 100644 storage/client/file/src/test/resources/session-records/deleteShareDoesNotExist.json create mode 100644 storage/client/file/src/test/resources/session-records/deleteSnapshotFromShareClient.json create mode 100644 storage/client/file/src/test/resources/session-records/deleteSubDirectory.json create mode 100644 storage/client/file/src/test/resources/session-records/deleteThenCreateFromShareClient.json create mode 100644 storage/client/file/src/test/resources/session-records/deleteThenCreateShareFromFileServiceClient.json create mode 100644 storage/client/file/src/test/resources/session-records/deleteThenCreateShareTooSoonFromFileServiceClient.json create mode 100644 storage/client/file/src/test/resources/session-records/deleteThenCreateTooSoonFromShareClient.json create mode 100644 storage/client/file/src/test/resources/session-records/downloadWithProperties.json create mode 100644 storage/client/file/src/test/resources/session-records/forceCloseHandlesFromDirClient.json create mode 100644 storage/client/file/src/test/resources/session-records/forceCloseHandlesFromFileClient.json create mode 100644 storage/client/file/src/test/resources/session-records/getDirectoryDoesNotCreateADirectory.json create mode 100644 storage/client/file/src/test/resources/session-records/getFileClientFromDirClient.json create mode 100644 storage/client/file/src/test/resources/session-records/getHandlesFromDirClient.json create mode 100644 storage/client/file/src/test/resources/session-records/getMetadataDoesNotExistFromShareClient.json create mode 100644 storage/client/file/src/test/resources/session-records/getMetadataFromShareClient.json create mode 100644 storage/client/file/src/test/resources/session-records/getPolicies.json create mode 100644 storage/client/file/src/test/resources/session-records/getPoliciesDoesNotExist.json create mode 100644 storage/client/file/src/test/resources/session-records/getPropertiesDoesNotExistFromShareClient.json create mode 100644 storage/client/file/src/test/resources/session-records/getPropertiesFromDirClient.json create mode 100644 storage/client/file/src/test/resources/session-records/getPropertiesFromFileClient.json create mode 100644 storage/client/file/src/test/resources/session-records/getPropertiesFromShareClient.json create mode 100644 storage/client/file/src/test/resources/session-records/getRootDirectoryDoesNotCreateADirectory.json create mode 100644 storage/client/file/src/test/resources/session-records/getShareDoesNotCreateAShare.json create mode 100644 storage/client/file/src/test/resources/session-records/getSnapshotId.json create mode 100644 storage/client/file/src/test/resources/session-records/getSnapshotMetadataDoesNotExistFromShareClient.json create mode 100644 storage/client/file/src/test/resources/session-records/getSnapshotMetadataFromShareClient.json create mode 100644 storage/client/file/src/test/resources/session-records/getSnapshotPropertiesDoesNotExist.json create mode 100644 storage/client/file/src/test/resources/session-records/getSnapshotPropertiesFromShareClient.json create mode 100644 storage/client/file/src/test/resources/session-records/getStats.json create mode 100644 storage/client/file/src/test/resources/session-records/getStatsDoesNotExist.json create mode 100644 storage/client/file/src/test/resources/session-records/getSubDirectoryClient.json create mode 100644 storage/client/file/src/test/resources/session-records/listFilesAndDirectoriesFromDirClient.json create mode 100644 storage/client/file/src/test/resources/session-records/listHandlesFromFileClient.json create mode 100644 storage/client/file/src/test/resources/session-records/listRangesFromFileClient.json create mode 100644 storage/client/file/src/test/resources/session-records/listShares.json create mode 100644 storage/client/file/src/test/resources/session-records/listSharesIncludeMetadata.json create mode 100644 storage/client/file/src/test/resources/session-records/listSharesIncludeMetadataAndSnapshots.json create mode 100644 storage/client/file/src/test/resources/session-records/listSharesIncludeSnapshots.json create mode 100644 storage/client/file/src/test/resources/session-records/listSharesInvalidMaxResults.json create mode 100644 storage/client/file/src/test/resources/session-records/listSharesWithLimit.json create mode 100644 storage/client/file/src/test/resources/session-records/listSharesWithPrefix.json create mode 100644 storage/client/file/src/test/resources/session-records/setFileServiceProperties.json create mode 100644 storage/client/file/src/test/resources/session-records/setHttpHeadersFromFileClient.json create mode 100644 storage/client/file/src/test/resources/session-records/setMeatadataFromFileClient.json create mode 100644 storage/client/file/src/test/resources/session-records/setMetadataDoesNotExistFromShareClient.json create mode 100644 storage/client/file/src/test/resources/session-records/setMetadataFromDirClient.json create mode 100644 storage/client/file/src/test/resources/session-records/setMetadataFromShareClient.json create mode 100644 storage/client/file/src/test/resources/session-records/setMetadataInvalidKeyFromDirClient.json create mode 100644 storage/client/file/src/test/resources/session-records/setMetadataInvalidMetadataFromShareClient.json create mode 100644 storage/client/file/src/test/resources/session-records/setPolicies.json create mode 100644 storage/client/file/src/test/resources/session-records/setPoliciesDoesNotExist.json create mode 100644 storage/client/file/src/test/resources/session-records/setPoliciesInvalidPermission.json create mode 100644 storage/client/file/src/test/resources/session-records/setPoliciesTooManyPermissions.json create mode 100644 storage/client/file/src/test/resources/session-records/setPropertiesDoesNotExistFromShareClient.json create mode 100644 storage/client/file/src/test/resources/session-records/setPropertiesFromShareClient.json create mode 100644 storage/client/file/src/test/resources/session-records/setPropertiesInvalidAllowedHeader.json create mode 100644 storage/client/file/src/test/resources/session-records/setPropertiesInvalidAllowedMethod.json create mode 100644 storage/client/file/src/test/resources/session-records/setPropertiesInvalidAllowedOrigin.json create mode 100644 storage/client/file/src/test/resources/session-records/setPropertiesInvalidExposedHeader.json create mode 100644 storage/client/file/src/test/resources/session-records/setPropertiesInvalidQuotaFromShareClient.json create mode 100644 storage/client/file/src/test/resources/session-records/setPropertiesTooManyRules.json create mode 100644 storage/client/file/src/test/resources/session-records/snapshot.json create mode 100644 storage/client/file/src/test/resources/session-records/snapshotDifferentMetadata.json create mode 100644 storage/client/file/src/test/resources/session-records/snapshotDoesNotExist.json create mode 100644 storage/client/file/src/test/resources/session-records/snapshotSameMetadata.json create mode 100644 storage/client/file/src/test/resources/session-records/startCopy.json create mode 100644 storage/client/file/src/test/resources/session-records/upload.json create mode 100644 storage/client/file/src/test/resources/session-records/uploadToStorageAndDownloadToFile.json create mode 100644 storage/client/file/src/test/resources/session-records/urlFromDirClient.json create mode 100644 storage/client/file/src/test/resources/testfiles/helloworld create mode 100644 storage/client/pom.xml 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) From fe9559f1e4cafbb805e64352f0b7a4b8ccfa8f83 Mon Sep 17 00:00:00 2001 From: Alan Zimmer <48699787+alzimmermsft@users.noreply.github.com> Date: Wed, 24 Jul 2019 09:34:04 -0700 Subject: [PATCH 09/17] Merge Storage Blob Client Builders (#4468) Merges AppendBlobClientBuilder, BlobClientBuilder, BlockBlobClientBuilder, and PageBlobClientBuilder into a single builder class BlobClientBuilder. Additionally, JavaDoc comments for the other builder classes, ContainerClientBuilder and StorageAccountClientBuilder, were cleaned up and the way the endpoint is handled in builders was changed. --- .../storage/blob/AppendBlobAsyncClient.java | 6 +- .../azure/storage/blob/AppendBlobClient.java | 4 +- .../storage/blob/AppendBlobClientBuilder.java | 333 ----------------- .../azure/storage/blob/BlobAsyncClient.java | 3 +- .../com/azure/storage/blob/BlobClient.java | 1 + .../azure/storage/blob/BlobClientBuilder.java | 171 +++++++-- .../storage/blob/BlockBlobAsyncClient.java | 4 +- .../azure/storage/blob/BlockBlobClient.java | 4 +- .../storage/blob/BlockBlobClientBuilder.java | 337 ------------------ .../storage/blob/ContainerClientBuilder.java | 53 +-- .../storage/blob/PageBlobAsyncClient.java | 4 +- .../azure/storage/blob/PageBlobClient.java | 4 +- .../storage/blob/PageBlobClientBuilder.java | 333 ----------------- .../storage/blob/SASQueryParameters.java | 20 +- .../storage/blob/StorageClientBuilder.java | 41 ++- .../credentials/SASTokenCredential.java | 151 +------- .../com/azure/storage/blob/APISpec.groovy | 10 +- .../com/azure/storage/blob/BlobAPITest.groovy | 7 +- .../storage/blob/ContainerAPITest.groovy | 8 +- .../com/azure/storage/blob/SASTest.groovy | 66 ++-- .../azure/storage/queue/QueueAsyncClient.java | 5 +- 21 files changed, 288 insertions(+), 1277 deletions(-) delete mode 100644 storage/client/blob/src/main/java/com/azure/storage/blob/AppendBlobClientBuilder.java delete mode 100644 storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobClientBuilder.java delete mode 100644 storage/client/blob/src/main/java/com/azure/storage/blob/PageBlobClientBuilder.java diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/AppendBlobAsyncClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/AppendBlobAsyncClient.java index 60376a3d990ab..7275f0fb326fe 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/AppendBlobAsyncClient.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/AppendBlobAsyncClient.java @@ -24,8 +24,8 @@ /** - * Client to an append blob. It may only be instantiated through a {@link AppendBlobClientBuilder#buildAsyncClient()}, via - * the method {@link BlobAsyncClient#asAppendBlobAsyncClient()}, or via the method + * Client to an append blob. It may only be instantiated through a {@link BlobClientBuilder#buildAppendBlobAsyncClient()}, + * via the method {@link BlobAsyncClient#asAppendBlobAsyncClient()}, or via the method * {@link ContainerAsyncClient#getAppendBlobAsyncClient(String)}. This class does not hold * any state about a particular blob, but is instead a convenient way of sending appropriate * requests to the resource on the service. @@ -58,7 +58,7 @@ public final class AppendBlobAsyncClient extends BlobAsyncClient { public static final int MAX_BLOCKS = 50000; /** - * Package-private constructor for use by {@link AppendBlobClientBuilder}. + * Package-private constructor for use by {@link BlobClientBuilder}. * @param azureBlobStorageBuilder the API client builder for blob storage API */ AppendBlobAsyncClient(AzureBlobStorageBuilder azureBlobStorageBuilder, String snapshot) { diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/AppendBlobClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/AppendBlobClient.java index 6be2bf7f4e5aa..246fe645af179 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/AppendBlobClient.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/AppendBlobClient.java @@ -23,7 +23,7 @@ /** - * Client to an append blob. It may only be instantiated through a {@link AppendBlobClientBuilder}, via + * Client to an append blob. It may only be instantiated through a {@link BlobClientBuilder}, via * the method {@link BlobClient#asAppendBlobClient()}, or via the method * {@link ContainerClient#getAppendBlobClient(String)}. This class does not hold * any state about a particular blob, but is instead a convenient way of sending appropriate @@ -51,7 +51,7 @@ public final class AppendBlobClient extends BlobClient { public static final int MAX_BLOCKS = AppendBlobAsyncClient.MAX_BLOCKS; /** - * Package-private constructor for use by {@link AppendBlobClientBuilder}. + * Package-private constructor for use by {@link BlobClientBuilder}. * @param appendBlobAsyncClient the async append blob client */ AppendBlobClient(AppendBlobAsyncClient appendBlobAsyncClient) { diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/AppendBlobClientBuilder.java b/storage/client/blob/src/main/java/com/azure/storage/blob/AppendBlobClientBuilder.java deleted file mode 100644 index c46883e7fecf9..0000000000000 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/AppendBlobClientBuilder.java +++ /dev/null @@ -1,333 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.azure.storage.blob; - -import com.azure.core.credentials.TokenCredential; -import com.azure.core.http.HttpClient; -import com.azure.core.http.HttpPipeline; -import com.azure.core.http.policy.AddDatePolicy; -import com.azure.core.http.policy.BearerTokenAuthenticationPolicy; -import com.azure.core.http.policy.HttpLogDetailLevel; -import com.azure.core.http.policy.HttpLoggingPolicy; -import com.azure.core.http.policy.HttpPipelinePolicy; -import com.azure.core.http.policy.RequestIdPolicy; -import com.azure.core.http.policy.UserAgentPolicy; -import com.azure.core.implementation.util.ImplUtils; -import com.azure.core.util.configuration.Configuration; -import com.azure.core.util.configuration.ConfigurationManager; -import com.azure.storage.blob.implementation.AzureBlobStorageBuilder; -import com.azure.storage.common.credentials.SASTokenCredential; -import com.azure.storage.common.credentials.SharedKeyCredential; -import com.azure.storage.common.policy.RequestRetryOptions; -import com.azure.storage.common.policy.RequestRetryPolicy; -import com.azure.storage.common.policy.SASTokenCredentialPolicy; -import com.azure.storage.common.policy.SharedKeyCredentialPolicy; - -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Objects; - -/** - * Fluent AppendBlobClientBuilder for instantiating a {@link AppendBlobClient} or {@link AppendBlobAsyncClient} - * using {@link AppendBlobClientBuilder#buildAsyncClient()} or {@link AppendBlobClientBuilder#buildAsyncClient()} respectively. - * - *

                  - * The following information must be provided on this builder: - * - *

                    - *
                  • the endpoint through {@code .endpoint()}, including the container name and blob name, in the format of {@code https://{accountName}.blob.core.windows.net/{containerName}/{blobName}}. - *
                  • the credential through {@code .credential()} or {@code .connectionString()} if the container is not publicly accessible. - *
                  - * - *

                  - * Once all the configurations are set on this builder, call {@code .buildClient()} to create a - * {@link AppendBlobClient} or {@code .buildAsyncClient()} to create a {@link AppendBlobAsyncClient}. - */ -public final class AppendBlobClientBuilder { - private static final String ACCOUNT_NAME = "accountname"; - private static final String ACCOUNT_KEY = "accountkey"; - private static final String ENDPOINT_PROTOCOL = "defaultendpointsprotocol"; - private static final String ENDPOINT_SUFFIX = "endpointsuffix"; - - private final List policies; - - private String endpoint; - private String containerName; - private String blobName; - private String snapshot; - private SharedKeyCredential sharedKeyCredential; - private TokenCredential tokenCredential; - private SASTokenCredential sasTokenCredential; - private HttpClient httpClient; - private HttpLogDetailLevel logLevel; - private RequestRetryOptions retryOptions; - private Configuration configuration; - - /** - * Creates a builder instance that is able to configure and construct {@link AppendBlobClient AppendBlobClients} - * and {@link AppendBlobAsyncClient AppendBlobAsyncClients}. - */ - public AppendBlobClientBuilder() { - retryOptions = new RequestRetryOptions(); - logLevel = HttpLogDetailLevel.NONE; - policies = new ArrayList<>(); - } - - private AzureBlobStorageBuilder buildImpl() { - Objects.requireNonNull(endpoint); - Objects.requireNonNull(containerName); - Objects.requireNonNull(blobName); - - // Closest to API goes first, closest to wire goes last. - final List policies = new ArrayList<>(); - - if (configuration == null) { - configuration = ConfigurationManager.getConfiguration(); - } - policies.add(new UserAgentPolicy(BlobConfiguration.NAME, BlobConfiguration.VERSION, configuration)); - policies.add(new RequestIdPolicy()); - policies.add(new AddDatePolicy()); - - if (sharedKeyCredential != null) { - policies.add(new SharedKeyCredentialPolicy(sharedKeyCredential)); - } else if (tokenCredential != null) { - policies.add(new BearerTokenAuthenticationPolicy(tokenCredential, String.format("%s/.default", endpoint))); - } else if (sasTokenCredential != null) { - policies.add(new SASTokenCredentialPolicy(sasTokenCredential)); - } else { - policies.add(new AnonymousCredentialPolicy()); - } - - policies.add(new RequestRetryPolicy(retryOptions)); - - policies.addAll(this.policies); - policies.add(new HttpLoggingPolicy(logLevel)); - - HttpPipeline pipeline = HttpPipeline.builder() - .policies(policies.toArray(new HttpPipelinePolicy[0])) - .httpClient(httpClient) - .build(); - - return new AzureBlobStorageBuilder() - .url(String.format("%s/%s/%s", endpoint, containerName, blobName)) - .pipeline(pipeline); - } - - /** - * @return a {@link AppendBlobClient} created from the configurations in this builder. - */ - public AppendBlobClient buildClient() { - return new AppendBlobClient(buildAsyncClient()); - } - - /** - * @return a {@link AppendBlobAsyncClient} created from the configurations in this builder. - */ - public AppendBlobAsyncClient buildAsyncClient() { - return new AppendBlobAsyncClient(buildImpl(), snapshot); - } - - /** - * Sets the service endpoint, additionally parses it for information (SAS token, container name, blob name) - * @param endpoint URL of the service - * @return the updated AppendBlobClientBuilder object - * @throws IllegalArgumentException If {@code endpoint} is a malformed URL or is using an unknown host. - */ - public AppendBlobClientBuilder endpoint(String endpoint) { - Objects.requireNonNull(endpoint); - URL url; - try { - url = new URL(endpoint); - BlobURLParts parts = URLParser.parse(url); - this.endpoint = parts.scheme() + "://" + parts.host(); - - if (parts.containerName() != null) { - this.containerName = parts.containerName(); - } - - if (parts.blobName() != null) { - this.blobName = parts.blobName(); - } - - if (parts.snapshot() != null) { - this.snapshot = parts.snapshot(); - } - } catch (MalformedURLException ex) { - throw new IllegalArgumentException("The Azure Storage Blob endpoint url is malformed."); - } - - SASTokenCredential credential = SASTokenCredential.fromQuery(url.getQuery()); - if (credential != null) { - this.credential(credential); - } - - return this; - } - - /** - * Sets the name of the container this client is connecting to. - * @param containerName the name of the container - * @return the updated AppendBlobClientBuilder object - */ - public AppendBlobClientBuilder containerName(String containerName) { - this.containerName = containerName; - return this; - } - - /** - * Sets the name of the blob this client is connecting to. - * @param blobName the name of the blob - * @return the updated AppendBlobClientBuilder object - */ - public AppendBlobClientBuilder blobName(String blobName) { - this.blobName = blobName; - return this; - } - - /** - * Sets the snapshot of the blob this client is connecting to. - * @param snapshot the snapshot identifier for the blob - * @return the updated AppendBlobClientBuilder object - */ - public AppendBlobClientBuilder snapshot(String snapshot) { - this.snapshot = snapshot; - return this; - } - - /** - * Sets the credential used to authorize requests sent to the service - * @param credential authorization credential - * @return the updated AppendBlobClientBuilder object - */ - public AppendBlobClientBuilder credential(SharedKeyCredential credential) { - this.sharedKeyCredential = credential; - this.tokenCredential = null; - this.sasTokenCredential = null; - return this; - } - - /** - * Sets the credential used to authorize requests sent to the service - * @param credential authorization credential - * @return the updated AppendBlobClientBuilder object - */ - public AppendBlobClientBuilder credential(TokenCredential credential) { - this.tokenCredential = credential; - this.sharedKeyCredential = null; - this.sasTokenCredential = null; - return this; - } - - /** - * Sets the credential used to authorize requests sent to the service - * @param credential authorization credential - * @return the updated AppendBlobClientBuilder object - */ - public AppendBlobClientBuilder credential(SASTokenCredential credential) { - this.sasTokenCredential = credential; - this.sharedKeyCredential = null; - this.tokenCredential = null; - return this; - } - - /** - * Clears the credential used to authorize requests sent to the service - * @return the updated AppendBlobClientBuilder object - */ - public AppendBlobClientBuilder anonymousCredential() { - this.sharedKeyCredential = null; - this.tokenCredential = null; - this.sasTokenCredential = null; - return this; - } - - /** - * Sets the connection string for the service, parses it for authentication information (account name, account key) - * @param connectionString connection string from access keys section - * @return the updated AppendBlobClientBuilder object - * @throws IllegalArgumentException If {@code connectionString} doesn't contain AccountName or AccountKey. - */ - public AppendBlobClientBuilder connectionString(String connectionString) { - Objects.requireNonNull(connectionString); - - Map connectionKVPs = new HashMap<>(); - for (String s : connectionString.split(";")) { - String[] kvp = s.split("=", 2); - connectionKVPs.put(kvp[0].toLowerCase(Locale.ROOT), kvp[1]); - } - - String accountName = connectionKVPs.get(ACCOUNT_NAME); - String accountKey = connectionKVPs.get(ACCOUNT_KEY); - String endpointProtocol = connectionKVPs.get(ENDPOINT_PROTOCOL); - String endpointSuffix = connectionKVPs.get(ENDPOINT_SUFFIX); - - if (ImplUtils.isNullOrEmpty(accountName) || ImplUtils.isNullOrEmpty(accountKey)) { - throw new IllegalArgumentException("Connection string must contain 'AccountName' and 'AccountKey'."); - } - - if (!ImplUtils.isNullOrEmpty(endpointProtocol) && !ImplUtils.isNullOrEmpty(endpointSuffix)) { - String endpoint = String.format("%s://%s.blob.%s", endpointProtocol, accountName, endpointSuffix.replaceFirst("^\\.", "")); - endpoint(endpoint); - } - - // Use accountName and accountKey to get the SAS token using the credential class. - return credential(new SharedKeyCredential(accountName, accountKey)); - } - - /** - * Sets the http client used to send service requests - * @param httpClient http client to send requests - * @return the updated AppendBlobClientBuilder object - */ - public AppendBlobClientBuilder httpClient(HttpClient httpClient) { - this.httpClient = httpClient; - return this; - } - - /** - * Adds a pipeline policy to apply on each request sent - * @param pipelinePolicy a pipeline policy - * @return the updated AppendBlobClientBuilder object - */ - public AppendBlobClientBuilder addPolicy(HttpPipelinePolicy pipelinePolicy) { - this.policies.add(pipelinePolicy); - return this; - } - - /** - * Sets the logging level for service requests - * @param logLevel logging level - * @return the updated AppendBlobClientBuilder object - */ - public AppendBlobClientBuilder httpLogDetailLevel(HttpLogDetailLevel logLevel) { - this.logLevel = logLevel; - return this; - } - - /** - * Sets the configuration object used to retrieve environment configuration values used to buildClient the client with - * when they are not set in the appendBlobClientBuilder, defaults to Configuration.NONE - * @param configuration configuration store - * @return the updated AppendBlobClientBuilder object - */ - public AppendBlobClientBuilder configuration(Configuration configuration) { - this.configuration = configuration; - return this; - } - - /** - * Sets the request retry options for all the requests made through the client. - * @param retryOptions the options to configure retry behaviors - * @return the updated AppendBlobClientBuilder object - */ - public AppendBlobClientBuilder retryOptions(RequestRetryOptions retryOptions) { - this.retryOptions = retryOptions; - return this; - } -} diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobAsyncClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobAsyncClient.java index c8ada7d8722fb..c8ceb3f311d3f 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobAsyncClient.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobAsyncClient.java @@ -71,11 +71,12 @@ * operation, until {@code .subscribe()} is called on the reactive response. You can simply convert one of these * responses to a {@link java.util.concurrent.CompletableFuture} object through {@link Mono#toFuture()}. */ +@SuppressWarnings({"unused", "WeakerAccess"}) public class BlobAsyncClient { private static final int BLOB_DEFAULT_DOWNLOAD_BLOCK_SIZE = 4 * Constants.MB; private static final int BLOB_MAX_DOWNLOAD_BLOCK_SIZE = 100 * Constants.MB; - protected final AzureBlobStorageImpl azureBlobStorage; + final AzureBlobStorageImpl azureBlobStorage; protected final String snapshot; /** diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobClient.java index a937b8ca47613..e2c6eab47a768 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobClient.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobClient.java @@ -45,6 +45,7 @@ * Please refer to the Azure * Docs for more information. */ +@SuppressWarnings({"unused", "WeakerAccess"}) public class BlobClient { private final BlobAsyncClient blobAsyncClient; diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobClientBuilder.java b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobClientBuilder.java index 2238af18e48e9..b0e3c98d8904a 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/BlobClientBuilder.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/BlobClientBuilder.java @@ -17,13 +17,17 @@ import com.azure.core.util.configuration.Configuration; import com.azure.core.util.configuration.ConfigurationManager; import com.azure.storage.blob.implementation.AzureBlobStorageBuilder; +import com.azure.storage.blob.models.PageRange; import com.azure.storage.common.credentials.SASTokenCredential; import com.azure.storage.common.credentials.SharedKeyCredential; import com.azure.storage.common.policy.RequestRetryOptions; import com.azure.storage.common.policy.RequestRetryPolicy; import com.azure.storage.common.policy.SASTokenCredentialPolicy; import com.azure.storage.common.policy.SharedKeyCredentialPolicy; +import reactor.core.publisher.Flux; +import java.io.InputStream; +import java.io.OutputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; @@ -34,8 +38,7 @@ import java.util.Objects; /** - * Fluent BlobClientBuilder for instantiating a {@link BlobClient} or {@link BlobAsyncClient} - * using {@link BlobClientBuilder#buildClient()} or {@link BlobClientBuilder#buildAsyncClient()} respectively. + * This class provides a fluent builder API to help aid the configuration and instantiation Storage Blob clients. * *

                  * The following information must be provided on this builder: @@ -46,8 +49,17 @@ *

                * *

                - * Once all the configurations are set on this builder, call {@code .buildClient()} to create a - * {@link BlobClient} or {@code .buildAsyncClient()} to create a {@link BlobAsyncClient}. + * Once all the configurations are set on this builder use the following mapping to construct the given client: + *

                  + *
                • {@link BlobClientBuilder#buildBlobClient()} - {@link BlobClient}
                • + *
                • {@link BlobClientBuilder#buildBlobAsyncClient()} - {@link BlobAsyncClient}
                • + *
                • {@link BlobClientBuilder#buildAppendBlobClient()} - {@link AppendBlobClient}
                • + *
                • {@link BlobClientBuilder#buildAppendBlobAsyncClient()} - {@link AppendBlobAsyncClient}
                • + *
                • {@link BlobClientBuilder#buildBlockBlobClient()} - {@link BlockBlobClient}
                • + *
                • {@link BlobClientBuilder#buildBlockBlobAsyncClient()} - {@link BlockBlobAsyncClient}
                • + *
                • {@link BlobClientBuilder#buildPageBlobClient()} - {@link PageBlobClient}
                • + *
                • {@link BlobClientBuilder#buildPageBlobAsyncClient()} - {@link PageBlobAsyncClient}
                • + *
                */ public final class BlobClientBuilder { private static final String ACCOUNT_NAME = "accountname"; @@ -70,8 +82,7 @@ public final class BlobClientBuilder { private Configuration configuration; /** - * Creates a builder instance that is able to configure and construct {@link BlobClient BlobClients} - * and {@link BlobAsyncClient BlobAsyncClients}. + * Creates a builder instance that is able to configure and construct Storage Blob clients. */ public BlobClientBuilder() { retryOptions = new RequestRetryOptions(); @@ -120,53 +131,130 @@ private AzureBlobStorageBuilder buildImpl() { } /** + * Creates a {@link BlobClient} based on options set in the Builder. BlobClients are used to perform generic blob + * methods such as {@link BlobClient#download(OutputStream) download} and + * {@link BlobClient#getProperties() get properties}, use this when the blob type is unknown. + * * @return a {@link BlobClient} created from the configurations in this builder. + * @throws NullPointerException If {@code endpoint}, {@code containerName}, or {@code blobName} is {@code null}. */ - public BlobClient buildClient() { - return new BlobClient(buildAsyncClient()); + public BlobClient buildBlobClient() { + return new BlobClient(buildBlobAsyncClient()); } /** + * Creates a {@link BlobAsyncClient} based on options set in the Builder. BlobAsyncClients are used to perform + * generic blob methods such as {@link BlobAsyncClient#download() download} and + * {@link BlobAsyncClient#getProperties()}, use this when the blob type is unknown. + * * @return a {@link BlobAsyncClient} created from the configurations in this builder. + * @throws NullPointerException If {@code endpoint}, {@code containerName}, or {@code blobName} is {@code null}. */ - public BlobAsyncClient buildAsyncClient() { + public BlobAsyncClient buildBlobAsyncClient() { return new BlobAsyncClient(buildImpl(), snapshot); } + /** + * Creates a {@link AppendBlobClient} based on options set in the Builder. AppendBlobClients are used to perform + * append blob specific operations such as {@link AppendBlobClient#appendBlock(InputStream, long) append block}, + * only use this when the blob is known to be an append blob. + * + * @return a {@link AppendBlobClient} created from the configurations in this builder. + * @throws NullPointerException If {@code endpoint}, {@code containerName}, or {@code blobName} is {@code null}. + */ + public AppendBlobClient buildAppendBlobClient() { + return new AppendBlobClient(buildAppendBlobAsyncClient()); + } + + /** + * Creates a {@link AppendBlobAsyncClient} based on options set in the Builder. AppendBlobAsyncClients are used to + * perform append blob specific operations such as {@link AppendBlobAsyncClient#appendBlock(Flux, long) append blob}, + * only use this when the blob is known to be an append blob. + * + * @return a {@link AppendBlobAsyncClient} created from the configurations in this builder. + * @throws NullPointerException If {@code endpoint}, {@code containerName}, or {@code blobName} is {@code null}. + */ + public AppendBlobAsyncClient buildAppendBlobAsyncClient() { + return new AppendBlobAsyncClient(buildImpl(), snapshot); + } + + /** + * Creates a {@link BlockBlobClient} based on options set in the Builder. BlockBlobClients are used to perform + * generic upload operations such as {@link BlockBlobClient#uploadFromFile(String) upload from file} and block + * blob specific operations such as {@link BlockBlobClient#stageBlock(String, InputStream, long) stage block} and + * {@link BlockBlobClient#commitBlockList(List)}, only use this when the blob is known to be a block blob. + * + * @return a {@link BlockBlobClient} created from the configurations in this builder. + * @throws NullPointerException If {@code endpoint}, {@code containerName}, or {@code blobName} is {@code null}. + */ + public BlockBlobClient buildBlockBlobClient() { + return new BlockBlobClient(buildBlockBlobAsyncClient()); + } + + /** + * Creates a {@link BlockBlobAsyncClient} based on options set in the Builder. BlockBlobAsyncClients are used to + * perform generic upload operations such as {@link BlockBlobAsyncClient#uploadFromFile(String) upload from file} + * and block blob specific operations such as {@link BlockBlobAsyncClient#stageBlock(String, Flux, long) stage block} + * and {@link BlockBlobAsyncClient#commitBlockList(List) commit block list}, only use this when the blob is known to + * be a block blob. + * + * @return a {@link BlockBlobAsyncClient} created from the configurations in this builder. + * @throws NullPointerException If {@code endpoint}, {@code containerName}, or {@code blobName} is {@code null}. + */ + public BlockBlobAsyncClient buildBlockBlobAsyncClient() { + return new BlockBlobAsyncClient(buildImpl(), snapshot); + } + + /** + * Creates a {@link PageBlobClient} based on options set in the Builder. PageBlobClients are used to perform page + * blob specific operations such as {@link PageBlobClient#uploadPages(PageRange, InputStream) upload pages} and + * {@link PageBlobClient#clearPages(PageRange) clear pages}, only use this when the blob is known to be a page blob. + * + * @return a {@link PageBlobClient} created from the configurations in this builder. + * @throws NullPointerException If {@code endpoint}, {@code containerName}, or {@code blobName} is {@code null}. + */ + public PageBlobClient buildPageBlobClient() { + return new PageBlobClient(buildPageBlobAsyncClient()); + } + + /** + * Creates a {@link PageBlobAsyncClient} based on options set in the Builder. PageBlobAsyncClients are used to + * perform page blob specific operations such as {@link PageBlobAsyncClient#uploadPages(PageRange, Flux) upload pages} + * and {@link PageBlobAsyncClient#clearPages(PageRange) clear pages}, only use this when the blob is known to be a + * page blob. + * + * @return a {@link PageBlobAsyncClient} created from the configurations in this builder. + * @throws NullPointerException If {@code endpoint}, {@code containerName}, or {@code blobName} is {@code null}. + */ + public PageBlobAsyncClient buildPageBlobAsyncClient() { + return new PageBlobAsyncClient(buildImpl(), snapshot); + } + /** * Sets the service endpoint, additionally parses it for information (SAS token, container name, blob name) * @param endpoint URL of the service * @return the updated BlobClientBuilder object - * @throws IllegalArgumentException If {@code endpoint} is a malformed URL. + * @throws IllegalArgumentException If {@code endpoint} is {@code null} or is a malformed URL. */ public BlobClientBuilder endpoint(String endpoint) { - Objects.requireNonNull(endpoint); - URL url; try { - url = new URL(endpoint); + URL url = new URL(endpoint); BlobURLParts parts = URLParser.parse(url); - this.endpoint = parts.scheme() + "://" + parts.host(); - - if (parts.containerName() != null) { - this.containerName = parts.containerName(); - } - - if (parts.blobName() != null) { - this.blobName = parts.blobName(); - } - if (parts.snapshot() != null) { - this.snapshot = parts.snapshot(); + this.endpoint = parts.scheme() + "://" + parts.host(); + this.containerName = parts.containerName(); + this.blobName = parts.blobName(); + this.snapshot = parts.snapshot(); + + this.sasTokenCredential = SASTokenCredential.fromQueryParameters(parts.sasQueryParameters()); + if (this.sasTokenCredential != null) { + this.tokenCredential = null; + this.sharedKeyCredential = null; } } catch (MalformedURLException ex) { throw new IllegalArgumentException("The Azure Storage Blob endpoint url is malformed."); } - SASTokenCredential credential = SASTokenCredential.fromQuery(url.getQuery()); - if (credential != null) { - this.credential(credential); - } - return this; } @@ -174,9 +262,10 @@ public BlobClientBuilder endpoint(String endpoint) { * Sets the name of the container this client is connecting to. * @param containerName the name of the container * @return the updated BlobClientBuilder object + * @throws NullPointerException If {@code containerName} is {@code null} */ public BlobClientBuilder containerName(String containerName) { - this.containerName = containerName; + this.containerName = Objects.requireNonNull(containerName); return this; } @@ -184,9 +273,10 @@ public BlobClientBuilder containerName(String containerName) { * Sets the name of the blob this client is connecting to. * @param blobName the name of the blob * @return the updated BlobClientBuilder object + * @throws NullPointerException If {@code blobName} is {@code null} */ public BlobClientBuilder blobName(String blobName) { - this.blobName = blobName; + this.blobName = Objects.requireNonNull(blobName); return this; } @@ -204,9 +294,10 @@ public BlobClientBuilder snapshot(String snapshot) { * Sets the credential used to authorize requests sent to the service * @param credential authorization credential * @return the updated BlobClientBuilder object + * @throws NullPointerException If {@code credential} is {@code null} */ public BlobClientBuilder credential(SharedKeyCredential credential) { - this.sharedKeyCredential = credential; + this.sharedKeyCredential = Objects.requireNonNull(credential); this.tokenCredential = null; this.sasTokenCredential = null; return this; @@ -216,9 +307,10 @@ public BlobClientBuilder credential(SharedKeyCredential credential) { * Sets the credential used to authorize requests sent to the service * @param credential authorization credential * @return the updated BlobClientBuilder object + * @throws NullPointerException If {@code credential} is {@code null} */ public BlobClientBuilder credential(TokenCredential credential) { - this.tokenCredential = credential; + this.tokenCredential = Objects.requireNonNull(credential); this.sharedKeyCredential = null; this.sasTokenCredential = null; return this; @@ -228,9 +320,10 @@ public BlobClientBuilder credential(TokenCredential credential) { * Sets the credential used to authorize requests sent to the service * @param credential authorization credential * @return the updated BlobClientBuilder object + * @throws NullPointerException If {@code credential} is {@code null} */ public BlobClientBuilder credential(SASTokenCredential credential) { - this.sasTokenCredential = credential; + this.sasTokenCredential = Objects.requireNonNull(credential); this.sharedKeyCredential = null; this.tokenCredential = null; return this; @@ -251,6 +344,7 @@ public BlobClientBuilder anonymousCredential() { * Sets the connection string for the service, parses it for authentication information (account name, account key) * @param connectionString connection string from access keys section * @return the updated BlobClientBuilder object + * @throws NullPointerException If {@code connectionString} is {@code null} * @throws IllegalArgumentException If {@code connectionString} doesn't contain AccountName or AccountKey. */ public BlobClientBuilder connectionString(String connectionString) { @@ -284,9 +378,10 @@ public BlobClientBuilder connectionString(String connectionString) { * Sets the http client used to send service requests * @param httpClient http client to send requests * @return the updated BlobClientBuilder object + * @throws NullPointerException If {@code httpClient} is {@code null} */ public BlobClientBuilder httpClient(HttpClient httpClient) { - this.httpClient = httpClient; + this.httpClient = Objects.requireNonNull(httpClient); return this; } @@ -294,9 +389,10 @@ public BlobClientBuilder httpClient(HttpClient httpClient) { * Adds a pipeline policy to apply on each request sent * @param pipelinePolicy a pipeline policy * @return the updated BlobClientBuilder object + * @throws NullPointerException If {@code pipelinePolicy} is {@code null} */ public BlobClientBuilder addPolicy(HttpPipelinePolicy pipelinePolicy) { - this.policies.add(pipelinePolicy); + this.policies.add(Objects.requireNonNull(pipelinePolicy)); return this; } @@ -325,9 +421,10 @@ public BlobClientBuilder configuration(Configuration configuration) { * Sets the request retry options for all the requests made through the client. * @param retryOptions the options to configure retry behaviors * @return the updated BlobClientBuilder object + * @throws NullPointerException If {@code retryOptions} is {@code null} */ public BlobClientBuilder retryOptions(RequestRetryOptions retryOptions) { - this.retryOptions = retryOptions; + this.retryOptions = Objects.requireNonNull(retryOptions); return this; } } diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobAsyncClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobAsyncClient.java index e7d8aa9b0c03d..cdb0a06fa68e2 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobAsyncClient.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobAsyncClient.java @@ -42,7 +42,7 @@ import static com.azure.storage.blob.Utility.postProcessResponse; /** - * Client to a block blob. It may only be instantiated through a {@link BlockBlobClientBuilder}, via + * Client to a block blob. It may only be instantiated through a {@link BlobClientBuilder}, via * the method {@link BlobAsyncClient#asBlockBlobAsyncClient()}, or via the method * {@link ContainerAsyncClient#getBlockBlobAsyncClient(String)}. This class does not hold * any state about a particular blob, but is instead a convenient way of sending appropriate @@ -84,7 +84,7 @@ public final class BlockBlobAsyncClient extends BlobAsyncClient { public static final int MAX_BLOCKS = 50000; /** - * Package-private constructor for use by {@link BlockBlobClientBuilder}. + * Package-private constructor for use by {@link BlobClientBuilder}. * @param azureBlobStorageBuilder the API client builder for blob storage API */ BlockBlobAsyncClient(AzureBlobStorageBuilder azureBlobStorageBuilder, String snapshot) { diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobClient.java index ec76f684c1bb4..6af92555c2b00 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobClient.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobClient.java @@ -28,7 +28,7 @@ import java.util.List; /** - * Client to a block blob. It may only be instantiated through a {@link BlockBlobClientBuilder}, via + * Client to a block blob. It may only be instantiated through a {@link BlobClientBuilder}, via * the method {@link BlobClient#asBlockBlobClient()}, or via the method * {@link ContainerClient#getBlockBlobClient(String)}. This class does not hold * any state about a particular blob, but is instead a convenient way of sending appropriate @@ -61,7 +61,7 @@ public final class BlockBlobClient extends BlobClient { public static final int MAX_BLOCKS = BlockBlobAsyncClient.MAX_BLOCKS; /** - * Package-private constructor for use by {@link BlockBlobClientBuilder}. + * Package-private constructor for use by {@link BlobClientBuilder}. * @param blockBlobAsyncClient the async block blob client */ BlockBlobClient(BlockBlobAsyncClient blockBlobAsyncClient) { diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobClientBuilder.java b/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobClientBuilder.java deleted file mode 100644 index 4774228c27648..0000000000000 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/BlockBlobClientBuilder.java +++ /dev/null @@ -1,337 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.azure.storage.blob; - -import com.azure.core.credentials.TokenCredential; -import com.azure.core.http.HttpClient; -import com.azure.core.http.HttpPipeline; -import com.azure.core.http.policy.AddDatePolicy; -import com.azure.core.http.policy.BearerTokenAuthenticationPolicy; -import com.azure.core.http.policy.HttpLogDetailLevel; -import com.azure.core.http.policy.HttpLoggingPolicy; -import com.azure.core.http.policy.HttpPipelinePolicy; -import com.azure.core.http.policy.RequestIdPolicy; -import com.azure.core.http.policy.UserAgentPolicy; -import com.azure.core.implementation.util.ImplUtils; -import com.azure.core.util.configuration.Configuration; -import com.azure.core.util.configuration.ConfigurationManager; -import com.azure.storage.blob.implementation.AzureBlobStorageBuilder; -import com.azure.storage.common.credentials.SASTokenCredential; -import com.azure.storage.common.credentials.SharedKeyCredential; -import com.azure.storage.common.policy.RequestRetryOptions; -import com.azure.storage.common.policy.RequestRetryPolicy; -import com.azure.storage.common.policy.SASTokenCredentialPolicy; -import com.azure.storage.common.policy.SharedKeyCredentialPolicy; - -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Objects; - -/** - * Fluent BlockBlobClientBuilder for instantiating a {@link BlockBlobClient} or {@link BlockBlobAsyncClient} - * using {@link BlockBlobClientBuilder#buildClient()} or {@link BlockBlobClientBuilder#buildAsyncClient()} respectively. - * - *

                - * The following information must be provided on this builder: - * - *

                  - *
                • the endpoint through {@code .endpoint()}, including the container name and blob name, in the format of {@code https://{accountName}.blob.core.windows.net/{containerName}/{blobName}}. - *
                • the credential through {@code .credential()} or {@code .connectionString()} if the container is not publicly accessible. - *
                - * - *

                - * Once all the configurations are set on this builder, call {@code .buildClient()} to create a - * {@link BlockBlobClient} or {@code .buildAsyncClient()} to create a {@link BlockBlobAsyncClient}. - */ -public final class BlockBlobClientBuilder { - private static final String ACCOUNT_NAME = "accountname"; - private static final String ACCOUNT_KEY = "accountkey"; - private static final String ENDPOINT_PROTOCOL = "defaultendpointsprotocol"; - private static final String ENDPOINT_SUFFIX = "endpointsuffix"; - - private final List policies; - - private String endpoint; - private String containerName; - private String blobName; - private String snapshot; - private SharedKeyCredential sharedKeyCredential; - private TokenCredential tokenCredential; - private SASTokenCredential sasTokenCredential; - private HttpClient httpClient; - private HttpLogDetailLevel logLevel; - private RequestRetryOptions retryOptions; - private Configuration configuration; - - /** - * Creates a builder instance that is able to configure and construct {@link BlockBlobClient BlockBlobClients} - * and {@link BlockBlobAsyncClient BlockBlobAsyncClients}. - */ - public BlockBlobClientBuilder() { - retryOptions = new RequestRetryOptions(); - logLevel = HttpLogDetailLevel.NONE; - policies = new ArrayList<>(); - } - - /** - * Constructs an instance of BlockBlobAsyncClient based on the configurations stored in the appendBlobClientBuilder. - * @return a new client instance - */ - private AzureBlobStorageBuilder buildImpl() { - Objects.requireNonNull(endpoint); - Objects.requireNonNull(containerName); - Objects.requireNonNull(blobName); - - // Closest to API goes first, closest to wire goes last. - final List policies = new ArrayList<>(); - - if (configuration == null) { - configuration = ConfigurationManager.getConfiguration(); - } - policies.add(new UserAgentPolicy(BlobConfiguration.NAME, BlobConfiguration.VERSION, configuration)); - policies.add(new RequestIdPolicy()); - policies.add(new AddDatePolicy()); - - if (sharedKeyCredential != null) { - policies.add(new SharedKeyCredentialPolicy(sharedKeyCredential)); - } else if (tokenCredential != null) { - policies.add(new BearerTokenAuthenticationPolicy(tokenCredential, String.format("%s/.default", endpoint))); - } else if (sasTokenCredential != null) { - policies.add(new SASTokenCredentialPolicy(sasTokenCredential)); - } else { - policies.add(new AnonymousCredentialPolicy()); - } - - policies.add(new RequestRetryPolicy(retryOptions)); - - policies.addAll(this.policies); - policies.add(new HttpLoggingPolicy(logLevel)); - - HttpPipeline pipeline = HttpPipeline.builder() - .policies(policies.toArray(new HttpPipelinePolicy[0])) - .httpClient(httpClient) - .build(); - - return new AzureBlobStorageBuilder() - .url(String.format("%s/%s/%s", endpoint, containerName, blobName)) - .pipeline(pipeline); - } - - /** - * @return a {@link BlockBlobClient} created from the configurations in this builder. - */ - public BlockBlobClient buildClient() { - return new BlockBlobClient(buildAsyncClient()); - } - - /** - * @return a {@link BlockBlobAsyncClient} created from the configurations in this builder. - */ - public BlockBlobAsyncClient buildAsyncClient() { - return new BlockBlobAsyncClient(buildImpl(), snapshot); - } - - /** - * Sets the service endpoint, additionally parses it for information (SAS token, container name, blob name) - * @param endpoint URL of the service - * @return the updated BlockBlobClientBuilder object - * @throws IllegalArgumentException If {@code endpoint} is a malformed URL. - */ - public BlockBlobClientBuilder endpoint(String endpoint) { - Objects.requireNonNull(endpoint); - URL url; - try { - url = new URL(endpoint); - BlobURLParts parts = URLParser.parse(url); - this.endpoint = parts.scheme() + "://" + parts.host(); - - if (parts.containerName() != null) { - this.containerName = parts.containerName(); - } - - if (parts.blobName() != null) { - this.blobName = parts.blobName(); - } - - if (parts.snapshot() != null) { - this.snapshot = parts.snapshot(); - } - } catch (MalformedURLException ex) { - throw new IllegalArgumentException("The Azure Storage Blob endpoint url is malformed."); - } - - SASTokenCredential credential = SASTokenCredential.fromQuery(url.getQuery()); - if (credential != null) { - this.credential(credential); - } - - return this; - } - - /** - * Sets the name of the container this client is connecting to. - * @param containerName the name of the container - * @return the updated BlockBlobClientBuilder object - */ - public BlockBlobClientBuilder containerName(String containerName) { - this.containerName = containerName; - return this; - } - - /** - * Sets the name of the blob this client is connecting to. - * @param blobName the name of the blob - * @return the updated BlockBlobClientBuilder object - */ - public BlockBlobClientBuilder blobName(String blobName) { - this.blobName = blobName; - return this; - } - - /** - * Sets the snapshot of the blob this client is connecting to. - * @param snapshot the snapshot identifier for the blob - * @return the updated BlockBlobClientBuilder object - */ - public BlockBlobClientBuilder snapshot(String snapshot) { - this.snapshot = snapshot; - return this; - } - - /** - * Sets the credential used to authorize requests sent to the service - * @param credential authorization credential - * @return the updated BlockBlobClientBuilder object - */ - public BlockBlobClientBuilder credential(SharedKeyCredential credential) { - this.sharedKeyCredential = credential; - this.tokenCredential = null; - this.sasTokenCredential = null; - return this; - } - - /** - * Sets the credential used to authorize requests sent to the service - * @param credential authorization credential - * @return the updated BlockBlobClientBuilder object - */ - public BlockBlobClientBuilder credential(TokenCredential credential) { - this.tokenCredential = credential; - this.sharedKeyCredential = null; - this.sasTokenCredential = null; - return this; - } - - /** - * Sets the credential used to authorize requests sent to the service - * @param credential authorization credential - * @return the updated BlockBlobClientBuilder object - */ - public BlockBlobClientBuilder credential(SASTokenCredential credential) { - this.sasTokenCredential = credential; - this.sharedKeyCredential = null; - this.tokenCredential = null; - return this; - } - - /** - * Clears the credential used to authorize requests sent to the service - * @return the updated BlockBlobClientBuilder object - */ - public BlockBlobClientBuilder anonymousCredential() { - this.sharedKeyCredential = null; - this.tokenCredential = null; - this.sasTokenCredential = null; - return this; - } - - /** - * Sets the connection string for the service, parses it for authentication information (account name, account key) - * @param connectionString connection string from access keys section - * @return the updated BlockBlobClientBuilder object - * @throws IllegalArgumentException If {@code connectionString} doesn't contain AccountName or AccountKey - */ - public BlockBlobClientBuilder connectionString(String connectionString) { - Objects.requireNonNull(connectionString); - - Map connectionKVPs = new HashMap<>(); - for (String s : connectionString.split(";")) { - String[] kvp = s.split("=", 2); - connectionKVPs.put(kvp[0].toLowerCase(Locale.ROOT), kvp[1]); - } - - String accountName = connectionKVPs.get(ACCOUNT_NAME); - String accountKey = connectionKVPs.get(ACCOUNT_KEY); - String endpointProtocol = connectionKVPs.get(ENDPOINT_PROTOCOL); - String endpointSuffix = connectionKVPs.get(ENDPOINT_SUFFIX); - - if (ImplUtils.isNullOrEmpty(accountName) || ImplUtils.isNullOrEmpty(accountKey)) { - throw new IllegalArgumentException("Connection string must contain 'AccountName' and 'AccountKey'."); - } - - if (!ImplUtils.isNullOrEmpty(endpointProtocol) && !ImplUtils.isNullOrEmpty(endpointSuffix)) { - String endpoint = String.format("%s://%s.blob.%s", endpointProtocol, accountName, endpointSuffix.replaceFirst("^\\.", "")); - endpoint(endpoint); - } - - // Use accountName and accountKey to get the SAS token using the credential class. - return credential(new SharedKeyCredential(accountName, accountKey)); - } - - /** - * Sets the http client used to send service requests - * @param httpClient http client to send requests - * @return the updated BlockBlobClientBuilder object - */ - public BlockBlobClientBuilder httpClient(HttpClient httpClient) { - this.httpClient = httpClient; - return this; - } - - /** - * Adds a pipeline policy to apply on each request sent - * @param pipelinePolicy a pipeline policy - * @return the updated BlockBlobClientBuilder object - */ - public BlockBlobClientBuilder addPolicy(HttpPipelinePolicy pipelinePolicy) { - this.policies.add(pipelinePolicy); - return this; - } - - /** - * Sets the logging level for service requests - * @param logLevel logging level - * @return the updated BlockBlobClientBuilder object - */ - public BlockBlobClientBuilder httpLogDetailLevel(HttpLogDetailLevel logLevel) { - this.logLevel = logLevel; - return this; - } - - /** - * Sets the configuration object used to retrieve environment configuration values used to buildClient the client with - * when they are not set in the appendBlobClientBuilder, defaults to Configuration.NONE - * @param configuration configuration store - * @return the updated BlockBlobClientBuilder object - */ - public BlockBlobClientBuilder configuration(Configuration configuration) { - this.configuration = configuration; - return this; - } - - /** - * Sets the request retry options for all the requests made through the client. - * @param retryOptions the options to configure retry behaviors - * @return the updated BlockBlobClientBuilder object - */ - public BlockBlobClientBuilder retryOptions(RequestRetryOptions retryOptions) { - this.retryOptions = retryOptions; - return this; - } -} diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerClientBuilder.java b/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerClientBuilder.java index c1e4e6bbdaeb2..7c9e9543ffd94 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerClientBuilder.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/ContainerClientBuilder.java @@ -121,14 +121,20 @@ private AzureBlobStorageBuilder buildImpl() { } /** + * Creates a {@link ContainerClient} based on options set in the Builder. + * * @return a {@link ContainerClient} created from the configurations in this builder. + * @throws NullPointerException If {@code endpoint} is {@code null} or {@code containerName} is {@code null}. */ public ContainerClient buildClient() { return new ContainerClient(buildAsyncClient()); } /** + * Creates a {@link ContainerAsyncClient} based on options set in the Builder. + * * @return a {@link ContainerAsyncClient} created from the configurations in this builder. + * @throws NullPointerException If {@code endpoint} is {@code null} or {@code containerName} is {@code null}. */ public ContainerAsyncClient buildAsyncClient() { return new ContainerAsyncClient(buildImpl()); @@ -138,32 +144,25 @@ public ContainerAsyncClient buildAsyncClient() { * Sets the service endpoint, additionally parses it for information (SAS token, container name) * @param endpoint URL of the service * @return the updated ContainerClientBuilder object - * @throws IllegalArgumentException If {@code endpoint} is a malformed URL. + * @throws IllegalArgumentException If {@code endpoint} is {@code null} or is a malformed URL. */ public ContainerClientBuilder endpoint(String endpoint) { - Objects.requireNonNull(endpoint); - URL url; try { - url = new URL(endpoint); - this.endpoint = url.getProtocol() + "://" + url.getAuthority(); - String path = url.getPath(); - if (path != null && !path.isEmpty() && !path.equals("/")) { - path = path.replaceAll("^/", "").replaceAll("/$", ""); - if (path.contains("/")) { - throw new IllegalArgumentException("Endpoint should contain exactly 0 or 1 path segments"); - } else { - this.containerName = path; - } + URL url = new URL(endpoint); + BlobURLParts parts = URLParser.parse(url); + + this.endpoint = parts.scheme() + "://" + parts.host(); + this.containerName = parts.containerName(); + + this.sasTokenCredential = SASTokenCredential.fromQueryParameters(parts.sasQueryParameters()); + if (this.sasTokenCredential != null) { + this.tokenCredential = null; + this.sharedKeyCredential = null; } } catch (MalformedURLException ex) { throw new IllegalArgumentException("The Azure Storage Blob endpoint url is malformed."); } - SASTokenCredential credential = SASTokenCredential.fromQuery(url.getQuery()); - if (credential != null) { - this.credential(credential); - } - return this; } @@ -185,9 +184,10 @@ String endpoint() { * Sets the credential used to authorize requests sent to the service * @param credential authorization credential * @return the updated ContainerClientBuilder object + * @throws NullPointerException If {@code credential} is {@code null}. */ public ContainerClientBuilder credential(SharedKeyCredential credential) { - this.sharedKeyCredential = credential; + this.sharedKeyCredential = Objects.requireNonNull(credential); this.tokenCredential = null; this.sasTokenCredential = null; return this; @@ -197,9 +197,10 @@ public ContainerClientBuilder credential(SharedKeyCredential credential) { * Sets the credential used to authorize requests sent to the service * @param credential authorization credential * @return the updated ContainerClientBuilder object + * @throws NullPointerException If {@code credential} is {@code null}. */ public ContainerClientBuilder credential(TokenCredential credential) { - this.tokenCredential = credential; + this.tokenCredential = Objects.requireNonNull(credential); this.sharedKeyCredential = null; this.sasTokenCredential = null; return this; @@ -209,9 +210,10 @@ public ContainerClientBuilder credential(TokenCredential credential) { * Sets the credential used to authorize requests sent to the service * @param credential authorization credential * @return the updated ContainerClientBuilder object + * @throws NullPointerException If {@code credential} is {@code null}. */ public ContainerClientBuilder credential(SASTokenCredential credential) { - this.sasTokenCredential = credential; + this.sasTokenCredential = Objects.requireNonNull(credential); this.sharedKeyCredential = null; this.tokenCredential = null; return this; @@ -265,9 +267,10 @@ public ContainerClientBuilder connectionString(String connectionString) { * Sets the http client used to send service requests * @param httpClient http client to send requests * @return the updated ContainerClientBuilder object + * @throws NullPointerException If {@code httpClient} is {@code null}. */ public ContainerClientBuilder httpClient(HttpClient httpClient) { - this.httpClient = httpClient; + this.httpClient = Objects.requireNonNull(httpClient); return this; } @@ -275,9 +278,10 @@ public ContainerClientBuilder httpClient(HttpClient httpClient) { * Adds a pipeline policy to apply on each request sent * @param pipelinePolicy a pipeline policy * @return the updated ContainerClientBuilder object + * @throws NullPointerException If {@code pipelinePolicy} is {@code null}. */ public ContainerClientBuilder addPolicy(HttpPipelinePolicy pipelinePolicy) { - this.policies.add(pipelinePolicy); + this.policies.add(Objects.requireNonNull(pipelinePolicy)); return this; } @@ -306,9 +310,10 @@ public ContainerClientBuilder configuration(Configuration configuration) { * Sets the request retry options for all the requests made through the client. * @param retryOptions the options to configure retry behaviors * @return the updated ContainerClientBuilder object + * @throws NullPointerException If {@code retryOptions} is {@code null}. */ public ContainerClientBuilder retryOptions(RequestRetryOptions retryOptions) { - this.retryOptions = retryOptions; + this.retryOptions = Objects.requireNonNull(retryOptions); return this; } } diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/PageBlobAsyncClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/PageBlobAsyncClient.java index 72f052fd27573..925f167b2ad91 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/PageBlobAsyncClient.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/PageBlobAsyncClient.java @@ -29,7 +29,7 @@ import static com.azure.storage.blob.Utility.postProcessResponse; /** - * Client to a page blob. It may only be instantiated through a {@link PageBlobClientBuilder}, via + * Client to a page blob. It may only be instantiated through a {@link BlobClientBuilder}, via * the method {@link BlobAsyncClient#asPageBlobAsyncClient()}, or via the method * {@link ContainerAsyncClient#getPageBlobAsyncClient(String)}. This class does not hold * any state about a particular blob, but is instead a convenient way of sending appropriate @@ -63,7 +63,7 @@ public final class PageBlobAsyncClient extends BlobAsyncClient { public static final int MAX_PUT_PAGES_BYTES = 4 * Constants.MB; /** - * Package-private constructor for use by {@link PageBlobClientBuilder}. + * Package-private constructor for use by {@link BlobClientBuilder}. * @param azureBlobStorageBuilder the API client builder for blob storage API */ PageBlobAsyncClient(AzureBlobStorageBuilder azureBlobStorageBuilder, String snapshot) { diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/PageBlobClient.java b/storage/client/blob/src/main/java/com/azure/storage/blob/PageBlobClient.java index 62d2146ea8d61..14c0ea4644ded 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/PageBlobClient.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/PageBlobClient.java @@ -26,7 +26,7 @@ import java.time.Duration; /** - * Client to a page blob. It may only be instantiated through a {@link PageBlobClientBuilder}, via + * Client to a page blob. It may only be instantiated through a {@link BlobClientBuilder}, via * the method {@link BlobClient#asPageBlobClient()}, or via the method * {@link ContainerClient#getPageBlobClient(String)}. This class does not hold * any state about a particular blob, but is instead a convenient way of sending appropriate @@ -54,7 +54,7 @@ public final class PageBlobClient extends BlobClient { public static final int MAX_PUT_PAGES_BYTES = PageBlobAsyncClient.MAX_PUT_PAGES_BYTES; /** - * Package-private constructor for use by {@link PageBlobClientBuilder}. + * Package-private constructor for use by {@link BlobClientBuilder}. * @param pageBlobAsyncClient the async page blob client */ PageBlobClient(PageBlobAsyncClient pageBlobAsyncClient) { diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/PageBlobClientBuilder.java b/storage/client/blob/src/main/java/com/azure/storage/blob/PageBlobClientBuilder.java deleted file mode 100644 index 77010e0607f84..0000000000000 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/PageBlobClientBuilder.java +++ /dev/null @@ -1,333 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.azure.storage.blob; - -import com.azure.core.credentials.TokenCredential; -import com.azure.core.http.HttpClient; -import com.azure.core.http.HttpPipeline; -import com.azure.core.http.policy.AddDatePolicy; -import com.azure.core.http.policy.BearerTokenAuthenticationPolicy; -import com.azure.core.http.policy.HttpLogDetailLevel; -import com.azure.core.http.policy.HttpLoggingPolicy; -import com.azure.core.http.policy.HttpPipelinePolicy; -import com.azure.core.http.policy.RequestIdPolicy; -import com.azure.core.http.policy.UserAgentPolicy; -import com.azure.core.implementation.util.ImplUtils; -import com.azure.core.util.configuration.Configuration; -import com.azure.core.util.configuration.ConfigurationManager; -import com.azure.storage.blob.implementation.AzureBlobStorageBuilder; -import com.azure.storage.common.credentials.SASTokenCredential; -import com.azure.storage.common.credentials.SharedKeyCredential; -import com.azure.storage.common.policy.RequestRetryOptions; -import com.azure.storage.common.policy.RequestRetryPolicy; -import com.azure.storage.common.policy.SASTokenCredentialPolicy; -import com.azure.storage.common.policy.SharedKeyCredentialPolicy; - -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Objects; - -/** - * Fluent PageBlobClientBuilder for instantiating a {@link PageBlobClient} or {@link PageBlobAsyncClient} - * using {@link PageBlobClientBuilder#buildClient()} or {@link PageBlobClientBuilder#buildAsyncClient()} respectively. - * - *

                - * The following information must be provided on this builder: - * - *

                  - *
                • the endpoint through {@code .endpoint()}, including the container name and blob name, in the format of {@code https://{accountName}.blob.core.windows.net/{containerName}/{blobName}}. - *
                • the credential through {@code .credential()} or {@code .connectionString()} if the container is not publicly accessible. - *
                - * - *

                - * Once all the configurations are set on this builder, call {@code .buildClient()} to create a - * {@link PageBlobClient} or {@code .buildAsyncClient()} to create a {@link PageBlobAsyncClient}. - */ -public final class PageBlobClientBuilder { - private static final String ACCOUNT_NAME = "accountname"; - private static final String ACCOUNT_KEY = "accountkey"; - private static final String ENDPOINT_PROTOCOL = "defaultendpointsprotocol"; - private static final String ENDPOINT_SUFFIX = "endpointsuffix"; - - private final List policies; - - private String endpoint; - private String containerName; - private String blobName; - private String snapshot; - private SharedKeyCredential sharedKeyCredential; - private TokenCredential tokenCredential; - private SASTokenCredential sasTokenCredential; - private HttpClient httpClient; - private HttpLogDetailLevel logLevel; - private RequestRetryOptions retryOptions; - private Configuration configuration; - - /** - * Creates a builder instance that is able to configure and construct {@link PageBlobClient PageBlobClients} - * and {@link PageBlobAsyncClient PageBlobAsyncClients}. - */ - public PageBlobClientBuilder() { - retryOptions = new RequestRetryOptions(); - logLevel = HttpLogDetailLevel.NONE; - policies = new ArrayList<>(); - } - - private AzureBlobStorageBuilder buildImpl() { - Objects.requireNonNull(endpoint); - Objects.requireNonNull(containerName); - Objects.requireNonNull(blobName); - - // Closest to API goes first, closest to wire goes last. - final List policies = new ArrayList<>(); - - if (configuration == null) { - configuration = ConfigurationManager.getConfiguration(); - } - policies.add(new UserAgentPolicy(BlobConfiguration.NAME, BlobConfiguration.VERSION, configuration)); - policies.add(new RequestIdPolicy()); - policies.add(new AddDatePolicy()); - - if (sharedKeyCredential != null) { - policies.add(new SharedKeyCredentialPolicy(sharedKeyCredential)); - } else if (tokenCredential != null) { - policies.add(new BearerTokenAuthenticationPolicy(tokenCredential, String.format("%s/.default", endpoint))); - } else if (sasTokenCredential != null) { - policies.add(new SASTokenCredentialPolicy(sasTokenCredential)); - } else { - policies.add(new AnonymousCredentialPolicy()); - } - - policies.add(new RequestRetryPolicy(retryOptions)); - - policies.addAll(this.policies); - policies.add(new HttpLoggingPolicy(logLevel)); - - HttpPipeline pipeline = HttpPipeline.builder() - .policies(policies.toArray(new HttpPipelinePolicy[0])) - .httpClient(httpClient) - .build(); - - return new AzureBlobStorageBuilder() - .url(String.format("%s/%s/%s", endpoint, containerName, blobName)) - .pipeline(pipeline); - } - - /** - * @return a {@link PageBlobClient} created from the configurations in this builder. - */ - public PageBlobClient buildClient() { - return new PageBlobClient(buildAsyncClient()); - } - - /** - * @return a {@link PageBlobAsyncClient} created from the configurations in this builder. - */ - public PageBlobAsyncClient buildAsyncClient() { - return new PageBlobAsyncClient(buildImpl(), snapshot); - } - - /** - * Sets the service endpoint, additionally parses it for information (SAS token, container name, blob name) - * @param endpoint URL of the service - * @return the updated PageBlobClientBuilder object - * @throws IllegalArgumentException If {@code endpoint} is a malformed URL. - */ - public PageBlobClientBuilder endpoint(String endpoint) { - Objects.requireNonNull(endpoint); - URL url; - try { - url = new URL(endpoint); - BlobURLParts parts = URLParser.parse(url); - this.endpoint = parts.scheme() + "://" + parts.host(); - - if (parts.containerName() != null) { - this.containerName = parts.containerName(); - } - - if (parts.blobName() != null) { - this.blobName = parts.blobName(); - } - - if (parts.snapshot() != null) { - this.snapshot = parts.snapshot(); - } - } catch (MalformedURLException ex) { - throw new IllegalArgumentException("The Azure Storage Blob endpoint url is malformed."); - } - - SASTokenCredential credential = SASTokenCredential.fromQuery(url.getQuery()); - if (credential != null) { - this.credential(credential); - } - - return this; - } - - /** - * Sets the name of the container this client is connecting to. - * @param containerName the name of the container - * @return the updated PageBlobClientBuilder object - */ - public PageBlobClientBuilder containerName(String containerName) { - this.containerName = containerName; - return this; - } - - /** - * Sets the name of the blob this client is connecting to. - * @param blobName the name of the blob - * @return the updated PageBlobClientBuilder object - */ - public PageBlobClientBuilder blobName(String blobName) { - this.blobName = blobName; - return this; - } - - /** - * Sets the snapshot of the blob this client is connecting to. - * @param snapshot the snapshot identifier for the blob - * @return the updated PageBlobClientBuilder object - */ - public PageBlobClientBuilder snapshot(String snapshot) { - this.snapshot = snapshot; - return this; - } - - /** - * Sets the credential used to authorize requests sent to the service - * @param credential authorization credential - * @return the updated PageBlobClientBuilder object - */ - public PageBlobClientBuilder credential(SharedKeyCredential credential) { - this.sharedKeyCredential = credential; - this.tokenCredential = null; - this.sasTokenCredential = null; - return this; - } - - /** - * Sets the credential used to authorize requests sent to the service - * @param credential authorization credential - * @return the updated PageBlobClientBuilder object - */ - public PageBlobClientBuilder credential(TokenCredential credential) { - this.tokenCredential = credential; - this.sharedKeyCredential = null; - this.sasTokenCredential = null; - return this; - } - - /** - * Sets the credential used to authorize requests sent to the service - * @param credential authorization credential - * @return the updated PageBlobClientBuilder object - */ - public PageBlobClientBuilder credential(SASTokenCredential credential) { - this.sasTokenCredential = credential; - this.sharedKeyCredential = null; - this.tokenCredential = null; - return this; - } - - /** - * Clears the credential used to authorize requests sent to the service - * @return the updated PageBlobClientBuilder object - */ - public PageBlobClientBuilder anonymousCredential() { - this.sharedKeyCredential = null; - this.tokenCredential = null; - this.sasTokenCredential = null; - return this; - } - - /** - * Sets the connection string for the service, parses it for authentication information (account name, account key) - * @param connectionString connection string from access keys section - * @return the updated PageBlobClientBuilder object - * @throws IllegalArgumentException If {@code connectionString} doesn't contain AccountName or AccountKey - */ - public PageBlobClientBuilder connectionString(String connectionString) { - Objects.requireNonNull(connectionString); - - Map connectionKVPs = new HashMap<>(); - for (String s : connectionString.split(";")) { - String[] kvp = s.split("=", 2); - connectionKVPs.put(kvp[0].toLowerCase(Locale.ROOT), kvp[1]); - } - - String accountName = connectionKVPs.get(ACCOUNT_NAME); - String accountKey = connectionKVPs.get(ACCOUNT_KEY); - String endpointProtocol = connectionKVPs.get(ENDPOINT_PROTOCOL); - String endpointSuffix = connectionKVPs.get(ENDPOINT_SUFFIX); - - if (ImplUtils.isNullOrEmpty(accountName) || ImplUtils.isNullOrEmpty(accountKey)) { - throw new IllegalArgumentException("Connection string must contain 'AccountName' and 'AccountKey'."); - } - - if (!ImplUtils.isNullOrEmpty(endpointProtocol) && !ImplUtils.isNullOrEmpty(endpointSuffix)) { - String endpoint = String.format("%s://%s.blob.%s", endpointProtocol, accountName, endpointSuffix.replaceFirst("^\\.", "")); - endpoint(endpoint); - } - - // Use accountName and accountKey to get the SAS token using the credential class. - return credential(new SharedKeyCredential(accountName, accountKey)); - } - - /** - * Sets the http client used to send service requests - * @param httpClient http client to send requests - * @return the updated PageBlobClientBuilder object - */ - public PageBlobClientBuilder httpClient(HttpClient httpClient) { - this.httpClient = httpClient; - return this; - } - - /** - * Adds a pipeline policy to apply on each request sent - * @param pipelinePolicy a pipeline policy - * @return the updated PageBlobClientBuilder object - */ - public PageBlobClientBuilder addPolicy(HttpPipelinePolicy pipelinePolicy) { - this.policies.add(pipelinePolicy); - return this; - } - - /** - * Sets the logging level for service requests - * @param logLevel logging level - * @return the updated PageBlobClientBuilder object - */ - public PageBlobClientBuilder httpLogDetailLevel(HttpLogDetailLevel logLevel) { - this.logLevel = logLevel; - return this; - } - - /** - * Sets the configuration object used to retrieve environment configuration values used to buildClient the client with - * when they are not set in the appendBlobClientBuilder, defaults to Configuration.NONE - * @param configuration configuration store - * @return the updated PageBlobClientBuilder object - */ - public PageBlobClientBuilder configuration(Configuration configuration) { - this.configuration = configuration; - return this; - } - - /** - * Sets the request retry options for all the requests made through the client. - * @param retryOptions the options to configure retry behaviors - * @return the updated PageBlobClientBuilder object - */ - public PageBlobClientBuilder retryOptions(RequestRetryOptions retryOptions) { - this.retryOptions = retryOptions; - return this; - } -} diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/SASQueryParameters.java b/storage/client/blob/src/main/java/com/azure/storage/blob/SASQueryParameters.java index cd918e636bbd4..399e7ea1b6e63 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/SASQueryParameters.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/SASQueryParameters.java @@ -19,7 +19,7 @@ * are existing query parameters, which might affect the appropriate means of appending these query parameters). * NOTE: Instances of this class are immutable to ensure thread safety. */ -final class SASQueryParameters { +public final class SASQueryParameters { private final String version; @@ -297,26 +297,44 @@ public String contentType() { return contentType; } + /** + * @return the object ID of the key. + */ public String keyOid() { return keyOid; } + /** + * @return the tenant ID of the key. + */ public String keyTid() { return keyTid; } + /** + * @return the datetime when the key becomes active. + */ public OffsetDateTime keyStart() { return keyStart; } + /** + * @return the datetime when the key expires. + */ public OffsetDateTime keyExpiry() { return keyExpiry; } + /** + * @return the services that are permitted by the key. + */ public String keyService() { return keyService; } + /** + * @return the service version that created the key. + */ public String keyVersion() { return keyVersion; } diff --git a/storage/client/blob/src/main/java/com/azure/storage/blob/StorageClientBuilder.java b/storage/client/blob/src/main/java/com/azure/storage/blob/StorageClientBuilder.java index 0aff9d26aa029..fbbdc0f438ac0 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/blob/StorageClientBuilder.java +++ b/storage/client/blob/src/main/java/com/azure/storage/blob/StorageClientBuilder.java @@ -115,14 +115,20 @@ private AzureBlobStorageBuilder buildImpl() { } /** + * Creates a {@link StorageClient} based on options set in the Builder. + * * @return a {@link StorageClient} created from the configurations in this builder. + * @throws NullPointerException If {@code endpoint} is {@code null}. */ public StorageClient buildClient() { return new StorageClient(buildAsyncClient()); } /** + * Creates a {@link StorageAsyncClient} based on options set in the Builder. + * * @return a {@link StorageAsyncClient} created from the configurations in this builder. + * @throws NullPointerException If {@code endpoint} is {@code null}. */ public StorageAsyncClient buildAsyncClient() { return new StorageAsyncClient(buildImpl()); @@ -132,23 +138,22 @@ public StorageAsyncClient buildAsyncClient() { * Sets the blob service endpoint, additionally parses it for information (SAS token, queue name) * @param endpoint URL of the service * @return the updated StorageClientBuilder object - * @throws IllegalArgumentException If {@code endpoint} is a malformed URL. + * @throws IllegalArgumentException If {@code endpoint} is {@code null} or is a malformed URL. */ public StorageClientBuilder endpoint(String endpoint) { - Objects.requireNonNull(endpoint); - URL url; try { - url = new URL(endpoint); + URL url = new URL(endpoint); this.endpoint = url.getProtocol() + "://" + url.getAuthority(); + + this.sasTokenCredential = SASTokenCredential.fromQueryParameters(URLParser.parse(url).sasQueryParameters()); + if (this.sasTokenCredential != null) { + this.tokenCredential = null; + this.sharedKeyCredential = null; + } } catch (MalformedURLException ex) { throw new IllegalArgumentException("The Azure Storage endpoint url is malformed."); } - SASTokenCredential credential = SASTokenCredential.fromQuery(url.getQuery()); - if (credential != null) { - this.credential(credential); - } - return this; } @@ -160,9 +165,10 @@ String endpoint() { * Sets the credential used to authorize requests sent to the service * @param credential authorization credential * @return the updated ContainerClientBuilder object + * @throws NullPointerException If {@code credential} is {@code null}. */ public StorageClientBuilder credential(SharedKeyCredential credential) { - this.sharedKeyCredential = credential; + this.sharedKeyCredential = Objects.requireNonNull(credential); this.tokenCredential = null; this.sasTokenCredential = null; return this; @@ -172,9 +178,10 @@ public StorageClientBuilder credential(SharedKeyCredential credential) { * Sets the credential used to authorize requests sent to the service * @param credential authorization credential * @return the updated StorageClientBuilder object + * @throws NullPointerException If {@code credential} is {@code null}. */ public StorageClientBuilder credential(TokenCredential credential) { - this.tokenCredential = credential; + this.tokenCredential = Objects.requireNonNull(credential); this.sharedKeyCredential = null; this.sasTokenCredential = null; return this; @@ -184,9 +191,10 @@ public StorageClientBuilder credential(TokenCredential credential) { * Sets the credential used to authorize requests sent to the service * @param credential authorization credential * @return the updated StorageClientBuilder object + * @throws NullPointerException If {@code credential} is {@code null}. */ public StorageClientBuilder credential(SASTokenCredential credential) { - this.sasTokenCredential = credential; + this.sasTokenCredential = Objects.requireNonNull(credential); this.sharedKeyCredential = null; this.tokenCredential = null; return this; @@ -240,9 +248,10 @@ public StorageClientBuilder connectionString(String connectionString) { * Sets the http client used to send service requests * @param httpClient http client to send requests * @return the updated StorageClientBuilder object + * @throws NullPointerException If {@code httpClient} is {@code null}. */ public StorageClientBuilder httpClient(HttpClient httpClient) { - this.httpClient = httpClient; + this.httpClient = Objects.requireNonNull(httpClient); return this; } @@ -250,9 +259,10 @@ public StorageClientBuilder httpClient(HttpClient httpClient) { * Adds a pipeline policy to apply on each request sent * @param pipelinePolicy a pipeline policy * @return the updated StorageClientBuilder object + * @throws NullPointerException If {@code pipelinePolicy} is {@code null}. */ public StorageClientBuilder addPolicy(HttpPipelinePolicy pipelinePolicy) { - this.policies.add(pipelinePolicy); + this.policies.add(Objects.requireNonNull(pipelinePolicy)); return this; } @@ -281,9 +291,10 @@ public StorageClientBuilder configuration(Configuration configuration) { * Sets the request retry options for all the requests made through the client. * @param retryOptions the options to configure retry behaviors * @return the updated StorageClientBuilder object + * @throws NullPointerException If {@code retryOptions} is {@code null}. */ public StorageClientBuilder retryOptions(RequestRetryOptions retryOptions) { - this.retryOptions = retryOptions; + this.retryOptions = Objects.requireNonNull(retryOptions); return this; } } diff --git a/storage/client/blob/src/main/java/com/azure/storage/common/credentials/SASTokenCredential.java b/storage/client/blob/src/main/java/com/azure/storage/common/credentials/SASTokenCredential.java index cff7bc91f7765..8a18f449c8c9f 100644 --- a/storage/client/blob/src/main/java/com/azure/storage/common/credentials/SASTokenCredential.java +++ b/storage/client/blob/src/main/java/com/azure/storage/common/credentials/SASTokenCredential.java @@ -4,41 +4,12 @@ package com.azure.storage.common.credentials; import com.azure.core.implementation.util.ImplUtils; - -import java.util.HashMap; +import com.azure.storage.blob.SASQueryParameters; /** * Holds a SAS token used for authenticating requests. */ public final class SASTokenCredential { - // Required SAS token pieces - private static final String SIGNED_VERSION = "sv"; - private static final String SIGNED_SERVICES = "ss"; - private static final String SIGNED_RESOURCE_TYPES = "srt"; - private static final String SIGNED_PERMISSIONS = "sp"; - private static final String SIGNED_EXPIRY = "se"; - private static final String SIGNATURE = "sig"; - private static final String SIGNED_RESOURCE = "sr"; - - // Optional SAS token pieces - private static final String SIGNED_START = "st"; - private static final String SIGNED_PROTOCOL = "spr"; - private static final String SIGNED_IP = "sip"; - - private static final String CACHE_CONTROL = "rscc"; - private static final String CONTENT_DISPOSITION = "rscd"; - private static final String CONTENT_ENCODING = "rsce"; - private static final String CONTENT_LANGUAGE = "rscl"; - private static final String CONTENT_TYPE = "rsct"; - - // Possible User Delegation Key pieces - private static final String SIGNED_KEY_O_ID = "skoid"; - private static final String SIGNED_KEY_T_ID = "sktid"; - private static final String SIGNED_KEY_START = "skt"; - private static final String SIGNED_KEY_EXPIRY = "ske"; - private static final String SIGNED_KEY_SERVICE = "sks"; - private static final String SIGNED_KEY_VERSION = "skv"; - private final String sasToken; /** @@ -46,7 +17,7 @@ public final class SASTokenCredential { * * @param sasToken SAS token used to authenticate requests with the service. */ - public SASTokenCredential(String sasToken) { + private SASTokenCredential(String sasToken) { this.sasToken = sasToken; } @@ -58,115 +29,31 @@ public String sasToken() { } /** - * Creates a SAS token credential from the passed URL query string + * Creates a SAS token credential from the passed SAS token. * - * @param query URL query used to build the SAS token - * @return a SAS token credential if the query param contains all the necessary pieces + * @param sasToken SAS token + * @return a SAS token credential if {@code sasToken} is not {@code null} or empty, otherwise null. */ - public static SASTokenCredential fromQuery(String query) { - if (ImplUtils.isNullOrEmpty(query)) { + public static SASTokenCredential fromSASTokenString(String sasToken) { + if (ImplUtils.isNullOrEmpty(sasToken)) { return null; } - HashMap queryParams = new HashMap<>(); - for (String queryParam : query.split("&")) { - String key = queryParam.split("=", 2)[0]; - queryParams.put(key, queryParam); - } + return new SASTokenCredential(sasToken); + } - /* Because ServiceSAS only requires expiry and permissions, both of which could be on the container - acl, the only guaranteed indication of a SAS is the signature. We'll let the service validate - the other query parameters. */ - if (!queryParams.containsKey(SIGNATURE)) { + /** + * Creates a SAS token credential from the passed {@link SASQueryParameters}. + * + * @param queryParameters SAS token query parameters object + * @return a SAS token credential if {@code queryParameters} is not {@code null} and has + * {@link SASQueryParameters#signature() signature} set, otherwise returns {@code null}. + */ + public static SASTokenCredential fromQueryParameters(SASQueryParameters queryParameters) { + if (queryParameters == null || ImplUtils.isNullOrEmpty(queryParameters.signature())) { return null; } - StringBuilder sasTokenBuilder = new StringBuilder(); - - if (queryParams.containsKey(SIGNED_VERSION)) { - sasTokenBuilder.append(queryParams.get(SIGNED_VERSION)); - } - - if (queryParams.containsKey(SIGNED_SERVICES)) { - sasTokenBuilder.append("&").append(queryParams.get(SIGNED_SERVICES)); - } - - if (queryParams.containsKey(SIGNED_RESOURCE_TYPES)) { - sasTokenBuilder.append("&").append(queryParams.get(SIGNED_RESOURCE_TYPES)); - } - - if (queryParams.containsKey(SIGNED_PERMISSIONS)) { - sasTokenBuilder.append("&").append(queryParams.get(SIGNED_PERMISSIONS)); - } - - if (queryParams.containsKey(SIGNED_RESOURCE)) { - sasTokenBuilder.append("&").append(queryParams.get(SIGNED_RESOURCE)); - } - - // SIGNED_START is optional - if (queryParams.containsKey(SIGNED_START)) { - sasTokenBuilder.append("&").append(queryParams.get(SIGNED_START)); - } - - sasTokenBuilder.append("&").append(queryParams.get(SIGNED_EXPIRY)); - - // SIGNED_IP is optional - if (queryParams.containsKey(SIGNED_IP)) { - sasTokenBuilder.append("&").append(queryParams.get(SIGNED_IP)); - } - - // SIGNED_PROTOCOL is optional - if (queryParams.containsKey(SIGNED_PROTOCOL)) { - sasTokenBuilder.append("&").append(queryParams.get(SIGNED_PROTOCOL)); - } - - if (queryParams.containsKey(CACHE_CONTROL)) { - sasTokenBuilder.append("&").append(queryParams.get(CACHE_CONTROL)); - } - - if (queryParams.containsKey(CONTENT_DISPOSITION)) { - sasTokenBuilder.append("&").append(queryParams.get(CONTENT_DISPOSITION)); - } - - if (queryParams.containsKey(CONTENT_ENCODING)) { - sasTokenBuilder.append("&").append(queryParams.get(CONTENT_ENCODING)); - } - - if (queryParams.containsKey(CONTENT_LANGUAGE)) { - sasTokenBuilder.append("&").append(queryParams.get(CONTENT_LANGUAGE)); - } - - if (queryParams.containsKey(CONTENT_TYPE)) { - sasTokenBuilder.append("&").append(queryParams.get(CONTENT_TYPE)); - } - - // User Delegation Key Parameters - if (queryParams.containsKey(SIGNED_KEY_O_ID)) { - sasTokenBuilder.append("&").append(queryParams.get(SIGNED_KEY_O_ID)); - } - - if (queryParams.containsKey(SIGNED_KEY_T_ID)) { - sasTokenBuilder.append("&").append(queryParams.get(SIGNED_KEY_T_ID)); - } - - if (queryParams.containsKey(SIGNED_KEY_START)) { - sasTokenBuilder.append("&").append(queryParams.get(SIGNED_KEY_START)); - } - - if (queryParams.containsKey(SIGNED_KEY_EXPIRY)) { - sasTokenBuilder.append("&").append(queryParams.get(SIGNED_KEY_EXPIRY)); - } - - if (queryParams.containsKey(SIGNED_KEY_SERVICE)) { - sasTokenBuilder.append("&").append(queryParams.get(SIGNED_KEY_SERVICE)); - } - - if (queryParams.containsKey(SIGNED_KEY_VERSION)) { - sasTokenBuilder.append("&").append(queryParams.get(SIGNED_KEY_VERSION)); - } - - sasTokenBuilder.append("&").append(queryParams.get(SIGNATURE)); - - return new SASTokenCredential(sasTokenBuilder.toString()); + return new SASTokenCredential(queryParameters.encode()); } } diff --git a/storage/client/blob/src/test/java/com/azure/storage/blob/APISpec.groovy b/storage/client/blob/src/test/java/com/azure/storage/blob/APISpec.groovy index c59095e5f66c6..fb306c17ff358 100644 --- a/storage/client/blob/src/test/java/com/azure/storage/blob/APISpec.groovy +++ b/storage/client/blob/src/test/java/com/azure/storage/blob/APISpec.groovy @@ -7,10 +7,8 @@ import com.azure.core.http.* import com.azure.core.http.policy.HttpLogDetailLevel import com.azure.core.http.policy.HttpPipelinePolicy import com.azure.core.http.rest.Response -import com.azure.core.util.Context import com.azure.core.util.configuration.ConfigurationManager import com.azure.identity.credential.EnvironmentCredential -import com.azure.storage.blob.BlobProperties import com.azure.storage.blob.models.* import com.azure.storage.common.credentials.SharedKeyCredential import org.junit.Assume @@ -42,8 +40,6 @@ class APISpec extends Specification { static final ByteBuffer defaultData = ByteBuffer.wrap(defaultText.getBytes(StandardCharsets.UTF_8)) - static final Flux defaultFlux = Flux.just(defaultData) - static final Supplier defaultInputStream = new Supplier() { @Override InputStream get() { @@ -112,10 +108,6 @@ class APISpec extends Specification { */ static final String defaultContextKey = "Key" - static final String defaultContextValue = "Value" - - static final Context defaultContext = new Context(defaultContextKey, defaultContextValue) - static String getTestName(ISpecificationContext ctx) { return ctx.getCurrentFeature().name.replace(' ', '').toLowerCase() } @@ -271,11 +263,13 @@ class APISpec extends Specification { } catch (Exception e) { } + try { blobStorageServiceURL = getGenericServiceURL(getGenericCreds("BLOB_STORAGE_")) } catch (Exception e) { } + try { premiumServiceURL = getGenericServiceURL(getGenericCreds("PREMIUM_STORAGE_")) } diff --git a/storage/client/blob/src/test/java/com/azure/storage/blob/BlobAPITest.groovy b/storage/client/blob/src/test/java/com/azure/storage/blob/BlobAPITest.groovy index 0cf250d85d174..d0be4d532642a 100644 --- a/storage/client/blob/src/test/java/com/azure/storage/blob/BlobAPITest.groovy +++ b/storage/client/blob/src/test/java/com/azure/storage/blob/BlobAPITest.groovy @@ -7,7 +7,6 @@ import com.azure.core.http.HttpHeaders import com.azure.core.http.rest.Response import com.azure.core.http.rest.VoidResponse import com.azure.core.implementation.util.ImplUtils -import com.azure.storage.blob.BlobProperties import com.azure.storage.blob.models.* import spock.lang.Unroll @@ -241,7 +240,7 @@ class BlobAPITest extends APISpec { .endpoint(bu.getBlobUrl().toString()) .snapshot(snapshot) .credential(primaryCreds) - .buildClient() + .buildBlobClient() ByteArrayOutputStream snapshotStream = new ByteArrayOutputStream() bu3.download(snapshotStream) snapshotStream.toByteArray() == originalStream.toByteArray() @@ -987,7 +986,7 @@ class BlobAPITest extends APISpec { .endpoint(bu.getBlobUrl().toString()) .credential(primaryCreds) .snapshot(snapshotResponse.value()) - .buildClient() + .buildBlobClient() then: bu2.getProperties().statusCode() == 200 @@ -1015,7 +1014,7 @@ class BlobAPITest extends APISpec { .endpoint(bu.getBlobUrl().toString()) .credential(primaryCreds) .snapshot(response.value()) - .buildClient() + .buildBlobClient() expect: response.statusCode() == 201 diff --git a/storage/client/blob/src/test/java/com/azure/storage/blob/ContainerAPITest.groovy b/storage/client/blob/src/test/java/com/azure/storage/blob/ContainerAPITest.groovy index 9b28d87cd7b31..86da9838d53bb 100644 --- a/storage/client/blob/src/test/java/com/azure/storage/blob/ContainerAPITest.groovy +++ b/storage/client/blob/src/test/java/com/azure/storage/blob/ContainerAPITest.groovy @@ -1539,11 +1539,11 @@ class ContainerAPITest extends APISpec { cu.create() } - AppendBlobClient bu = new AppendBlobClientBuilder() + AppendBlobClient bu = new BlobClientBuilder() .credential(primaryCreds) .endpoint("http://" + primaryCreds.accountName() + ".blob.core.windows.net/\$root/rootblob") .httpClient(getHttpClient()) - .buildClient() + .buildAppendBlobClient() when: Response createResponse = bu.create() @@ -1565,11 +1565,11 @@ class ContainerAPITest extends APISpec { cu.create() } - AppendBlobClient bu = new AppendBlobClientBuilder() + AppendBlobClient bu = new BlobClientBuilder() .credential(primaryCreds) .endpoint("http://" + primaryCreds.accountName() + ".blob.core.windows.net/rootblob") .httpClient(getHttpClient()) - .buildClient() + .buildAppendBlobClient() when: Response createResponse = bu.create() diff --git a/storage/client/blob/src/test/java/com/azure/storage/blob/SASTest.groovy b/storage/client/blob/src/test/java/com/azure/storage/blob/SASTest.groovy index 1ebf9860f2ac3..2824ac1d3067d 100644 --- a/storage/client/blob/src/test/java/com/azure/storage/blob/SASTest.groovy +++ b/storage/client/blob/src/test/java/com/azure/storage/blob/SASTest.groovy @@ -135,12 +135,12 @@ class SASTest extends APISpec { when: def sas = bu.generateSAS(null, permissions, expiryTime, startTime, null, sasProtocol, ipRange, cacheControl, contentDisposition, contentEncoding, contentLanguage, contentType) - def builder = new BlockBlobClientBuilder() - builder.endpoint(cu.getContainerUrl().toString()) + def client = new BlobClientBuilder() + .endpoint(cu.getContainerUrl().toString()) .blobName(blobName) - .credential(new SASTokenCredential(sas)) + .credential(SASTokenCredential.fromSASTokenString(sas)) .httpClient(getHttpClient()) - def client = builder.buildClient() + .buildBlockBlobClient() def os = new ByteArrayOutputStream() client.download(os) @@ -187,13 +187,13 @@ class SASTest extends APISpec { when: def sas = snapshotBlob.generateSAS(null, permissions, expiryTime, startTime, null, sasProtocol, ipRange, cacheControl, contentDisposition, contentEncoding, contentLanguage, contentType) - def builder = new BlockBlobClientBuilder() - builder.endpoint(cu.getContainerUrl().toString()) + def client = new BlobClientBuilder() + .endpoint(cu.getContainerUrl().toString()) .blobName(blobName) .snapshot(snapshotId) - .credential(new SASTokenCredential(sas)) + .credential(SASTokenCredential.fromSASTokenString(sas)) .httpClient(getHttpClient()) - def client = builder.buildClient() + .buildBlockBlobClient() def os = new ByteArrayOutputStream() client.download(os) @@ -227,7 +227,7 @@ class SASTest extends APISpec { def builder1 = new ContainerClientBuilder() builder1.endpoint(cu.getContainerUrl().toString()) - .credential(new SASTokenCredential(sasWithId)) + .credential(SASTokenCredential.fromSASTokenString(sasWithId)) .httpClient(getHttpClient()) def client1 = builder1.buildClient() @@ -237,7 +237,7 @@ class SASTest extends APISpec { def builder2 = new ContainerClientBuilder() builder2.endpoint(cu.getContainerUrl().toString()) - .credential(new SASTokenCredential(sasWithPermissions)) + .credential(SASTokenCredential.fromSASTokenString(sasWithPermissions)) .httpClient(getHttpClient()) def client2 = builder2.buildClient() @@ -279,12 +279,12 @@ class SASTest extends APISpec { def sas = bu.generateUserDelegationSAS(key, cu.getContainerUrl().getHost().split("\\.")[0], permissions, expiryTime, startTime, null, sasProtocol, ipRange, cacheControl, contentDisposition, contentEncoding, contentLanguage, contentType) - def builder = new BlockBlobClientBuilder() - builder.endpoint(cu.getContainerUrl().toString()) + def client = new BlobClientBuilder() + .endpoint(cu.getContainerUrl().toString()) .blobName(blobName) - .credential(new SASTokenCredential(sas)) + .credential(SASTokenCredential.fromSASTokenString(sas)) .httpClient(getHttpClient()) - def client = builder.buildClient() + .buildBlockBlobClient() def os = new ByteArrayOutputStream() client.download(os) @@ -333,12 +333,12 @@ class SASTest extends APISpec { def sas = snapshotBlob.generateUserDelegationSAS(key, cu.getContainerUrl().getHost().split("\\.")[0], permissions, expiryTime, startTime, null, sasProtocol, ipRange, cacheControl, contentDisposition, contentEncoding, contentLanguage, contentType) // base blob with snapshot SAS - def builder1 = new BlockBlobClientBuilder() - builder1.endpoint(cu.getContainerUrl().toString()) + def client1 = new BlobClientBuilder() + .endpoint(cu.getContainerUrl().toString()) .blobName(blobName) - .credential(new SASTokenCredential(sas)) + .credential(SASTokenCredential.fromSASTokenString(sas)) .httpClient(getHttpClient()) - def client1 = builder1.buildClient() + .buildBlockBlobClient() client1.download(new ByteArrayOutputStream()) then: @@ -348,13 +348,13 @@ class SASTest extends APISpec { when: // blob snapshot with snapshot SAS - def builder2 = new BlockBlobClientBuilder() - builder2.endpoint(cu.getContainerUrl().toString()) + def client2 = new BlobClientBuilder() + .endpoint(cu.getContainerUrl().toString()) .blobName(blobName) .snapshot(snapshotId) - .credential(new SASTokenCredential(sas)) + .credential(SASTokenCredential.fromSASTokenString(sas)) .httpClient(getHttpClient()) - def client2 = builder2.buildClient() + .buildBlockBlobClient() def os = new ByteArrayOutputStream() client2.download(os) @@ -390,7 +390,7 @@ class SASTest extends APISpec { def builder = new ContainerClientBuilder() builder.endpoint(cu.getContainerUrl().toString()) - .credential(new SASTokenCredential(sasWithPermissions)) + .credential(SASTokenCredential.fromSASTokenString(sasWithPermissions)) .httpClient(getHttpClient()) def client = builder.buildClient() @@ -420,12 +420,12 @@ class SASTest extends APISpec { when: def sas = primaryServiceURL.generateAccountSAS(service, resourceType, permissions, expiryTime, null, null, null, null) - def builder = new BlockBlobClientBuilder() - builder.endpoint(cu.getContainerUrl().toString()) + def client = new BlobClientBuilder() + .endpoint(cu.getContainerUrl().toString()) .blobName(blobName) - .credential(new SASTokenCredential(sas)) + .credential(SASTokenCredential.fromSASTokenString(sas)) .httpClient(getHttpClient()) - def client = builder.buildClient() + .buildBlockBlobClient() def os = new ByteArrayOutputStream() client.download(os) @@ -454,12 +454,12 @@ class SASTest extends APISpec { when: def sas = primaryServiceURL.generateAccountSAS(service, resourceType, permissions, expiryTime, null, null, null, null) - def builder = new BlockBlobClientBuilder() - builder.endpoint(cu.getContainerUrl().toString()) + def client = new BlobClientBuilder() + .endpoint(cu.getContainerUrl().toString()) .blobName(blobName) - .credential(new SASTokenCredential(sas)) + .credential(SASTokenCredential.fromSASTokenString(sas)) .httpClient(getHttpClient()) - def client = builder.buildClient() + .buildBlockBlobClient() client.delete() then: @@ -485,7 +485,7 @@ class SASTest extends APISpec { def scBuilder = new StorageClientBuilder() scBuilder.endpoint(primaryServiceURL.getAccountUrl().toString()) .httpClient(getHttpClient()) - .credential(new SASTokenCredential(sas)) + .credential(SASTokenCredential.fromSASTokenString(sas)) def sc = scBuilder.buildClient() sc.createContainer("container") @@ -512,7 +512,7 @@ class SASTest extends APISpec { def scBuilder = new StorageClientBuilder() scBuilder.endpoint(primaryServiceURL.getAccountUrl().toString()) .httpClient(getHttpClient()) - .credential(new SASTokenCredential(sas)) + .credential(SASTokenCredential.fromSASTokenString(sas)) def sc = scBuilder.buildClient() sc.createContainer("container") diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/QueueAsyncClient.java b/storage/client/queue/src/main/java/com/azure/storage/queue/QueueAsyncClient.java index 2d3bd7636aeaf..8df2931f44d22 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/QueueAsyncClient.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/QueueAsyncClient.java @@ -24,13 +24,14 @@ import com.azure.storage.queue.models.SignedIdentifier; import com.azure.storage.queue.models.StorageErrorException; import com.azure.storage.queue.models.UpdatedMessage; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + import java.net.MalformedURLException; import java.net.URL; import java.time.Duration; import java.util.List; import java.util.Map; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; /** * This class provides a client that contains all the operations for interacting with a queue in Azure Storage Queue. From e19ea2b352e3fe167f4b834f4ec1a86490e72c8a Mon Sep 17 00:00:00 2001 From: Jianghao Lu Date: Wed, 24 Jul 2019 10:22:35 -0700 Subject: [PATCH 10/17] Regenerate blob file queue after merge --- .../AzureFileStorageBuilder.java | 6 +- .../file/implementation/DirectorysImpl.java | 124 +++--------------- .../file/implementation/FilesImpl.java | 113 +++++----------- .../file/implementation/ServicesImpl.java | 11 +- .../file/implementation/SharesImpl.java | 69 ++++------ ...istFilesAndDirectoriesSegmentResponse.java | 10 +- .../models/ServicesGetPropertiesResponse.java | 6 +- .../storage/file/models/ShareProperties.java | 15 --- .../AzureQueueStorageBuilder.java | 4 +- .../queue/implementation/MessageIdsImpl.java | 8 +- .../queue/implementation/MessagesImpl.java | 18 +-- .../queue/implementation/QueuesImpl.java | 32 ++--- .../storage/queue/models/DequeuedMessage.java | 3 + .../storage/queue/models/PeekedMessage.java | 3 +- 14 files changed, 131 insertions(+), 291 deletions(-) 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 35a1767ce3687..07a401015b89c 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 @@ -74,9 +74,9 @@ public AzureFileStorageImpl build() { this.pipeline = RestProxy.createDefaultPipeline(); } AzureFileStorageImpl client = new AzureFileStorageImpl(pipeline); - - client.version(this.version); - + if (this.version != null) { + 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 216f3c4cc7d5b..b7cedcaad9b81 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 @@ -25,7 +25,6 @@ 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 java.util.Map; import reactor.core.publisher.Mono; @@ -65,49 +64,42 @@ private interface DirectorysService { @Put("{shareName}/{directory}") @ExpectedResponses({201}) @UnexpectedResponseExceptionType(StorageErrorException.class) - 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); + 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); @Get("{shareName}/{directory}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - 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); + 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); @Delete("{shareName}/{directory}") @ExpectedResponses({202}) @UnexpectedResponseExceptionType(StorageErrorException.class) - 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); + Mono delete(@HostParam("url") String url, @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, @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); + 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); @Get("{shareName}/{directory}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - 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); + 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); @Get("{shareName}/{directory}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - 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); + 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); @Put("{shareName}/{directory}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - 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); + 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); } /** * 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. @@ -117,14 +109,12 @@ public Mono createWithRestResponseAsync(Context contex final Integer timeout = null; final Map metadata = null; final String restype = "directory"; - return service.create(this.client.url(), shareName, directoryName, timeout, metadata, this.client.version(), restype, context); + return service.create(this.client.url(), 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. @@ -134,30 +124,12 @@ public Mono createWithRestResponseAsync(Context contex @ServiceMethod(returns = ReturnType.SINGLE) public Mono createWithRestResponseAsync(Integer timeout, Map metadata, Context context) { final String restype = "directory"; - 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); + return service.create(this.client.url(), 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. @@ -167,14 +139,12 @@ public Mono getPropertiesWithRestResponseAsync( final String sharesnapshot = null; final Integer timeout = null; final String restype = "directory"; - return service.getProperties(this.client.url(), shareName, directoryName, sharesnapshot, timeout, this.client.version(), restype, context); + return service.getProperties(this.client.url(), 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. @@ -184,14 +154,12 @@ public Mono getPropertiesWithRestResponseAsync( @ServiceMethod(returns = ReturnType.SINGLE) public Mono getPropertiesWithRestResponseAsync(String sharesnapshot, Integer timeout, Context context) { final String restype = "directory"; - return service.getProperties(this.client.url(), shareName, directoryName, sharesnapshot, timeout, this.client.version(), restype, context); + return service.getProperties(this.client.url(), 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. @@ -200,46 +168,12 @@ public Mono getPropertiesWithRestResponseAsync( public Mono deleteWithRestResponseAsync(Context context) { final Integer timeout = null; final String restype = "directory"; - return service.delete(this.client.url(), shareName, directoryName, timeout, this.client.version(), restype, context); + return service.delete(this.client.url(), 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. @@ -248,14 +182,12 @@ public Mono deleteSubWithRestResponseAsync(String shar @ServiceMethod(returns = ReturnType.SINGLE) public Mono deleteWithRestResponseAsync(Integer timeout, Context context) { final String restype = "directory"; - return service.delete(this.client.url(), shareName, directoryName, fileName, timeout, this.client.version(), restype, context); + return service.delete(this.client.url(), 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. @@ -266,14 +198,12 @@ public Mono setMetadataWithRestResponseAsync(Cont final Map metadata = null; final String restype = "directory"; final String comp = "metadata"; - return service.setMetadata(this.client.url(), shareName, directoryName, timeout, metadata, this.client.version(), restype, comp, context); + return service.setMetadata(this.client.url(), 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. @@ -284,14 +214,12 @@ public Mono setMetadataWithRestResponseAsync(Cont public Mono setMetadataWithRestResponseAsync(Integer timeout, Map metadata, Context context) { final String restype = "directory"; final String comp = "metadata"; - return service.setMetadata(this.client.url(), shareName, directoryName, timeout, metadata, this.client.version(), restype, comp, context); + return service.setMetadata(this.client.url(), 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. @@ -305,14 +233,12 @@ public Mono listFilesAndDirect final Integer timeout = null; final String restype = "directory"; final String comp = "list"; - return service.listFilesAndDirectoriesSegment(this.client.url(), shareName, directoryName, prefix, sharesnapshot, marker, maxresults, timeout, this.client.version(), restype, comp, context); + return service.listFilesAndDirectoriesSegment(this.client.url(), 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. @@ -326,14 +252,12 @@ public Mono listFilesAndDirect public Mono listFilesAndDirectoriesSegmentWithRestResponseAsync(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(), shareName, directoryName, prefix, sharesnapshot, marker, maxresults, timeout, this.client.version(), restype, comp, context); + return service.listFilesAndDirectoriesSegment(this.client.url(), 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. @@ -346,14 +270,12 @@ public Mono listHandlesWithRestResponseAsync(Cont final String sharesnapshot = null; final Boolean recursive = null; final String comp = "listhandles"; - return service.listHandles(this.client.url(), shareName, directoryName, marker, maxresults, timeout, sharesnapshot, recursive, this.client.version(), comp, context); + return service.listHandles(this.client.url(), 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>. @@ -366,14 +288,12 @@ public Mono listHandlesWithRestResponseAsync(Cont @ServiceMethod(returns = ReturnType.SINGLE) public Mono listHandlesWithRestResponseAsync(String marker, Integer maxresults, Integer timeout, String sharesnapshot, Boolean recursive, Context context) { final String comp = "listhandles"; - return service.listHandles(this.client.url(), shareName, directoryName, marker, maxresults, timeout, sharesnapshot, recursive, this.client.version(), comp, context); + return service.listHandles(this.client.url(), 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. @@ -386,14 +306,12 @@ public Mono forceCloseHandlesWithRestRespon final String sharesnapshot = null; final Boolean recursive = null; final String comp = "forceclosehandles"; - return service.forceCloseHandles(this.client.url(), shareName, directoryName, timeout, marker, sharesnapshot, handleId, recursive, this.client.version(), comp, context); + return service.forceCloseHandles(this.client.url(), 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. @@ -406,6 +324,6 @@ public Mono forceCloseHandlesWithRestRespon @ServiceMethod(returns = ReturnType.SINGLE) public Mono forceCloseHandlesWithRestResponseAsync(String handleId, Integer timeout, String marker, String sharesnapshot, Boolean recursive, Context context) { final String comp = "forceclosehandles"; - return service.forceCloseHandles(this.client.url(), shareName, directoryName, timeout, marker, sharesnapshot, handleId, recursive, this.client.version(), comp, context); + return service.forceCloseHandles(this.client.url(), 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 91fe13e1a42d7..b8f344dba8f82 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 @@ -76,69 +76,66 @@ private interface FilesService { @Put("{shareName}/{directory}/{fileName}") @ExpectedResponses({201}) @UnexpectedResponseExceptionType(StorageErrorException.class) - 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); + 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); @Get("{shareName}/{directory}/{fileName}") @ExpectedResponses({200, 206}) @UnexpectedResponseExceptionType(StorageErrorException.class) - 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); + 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); @Head("{shareName}/{directory}/{fileName}") @ExpectedResponses({200}) - @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); + Mono getProperties(@HostParam("url") String url, @QueryParam("sharesnapshot") String sharesnapshot, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, Context context); @Delete("{shareName}/{directory}/{fileName}") @ExpectedResponses({202}) @UnexpectedResponseExceptionType(StorageErrorException.class) - 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); + Mono delete(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, Context context); @Put("{shareName}/{directory}/{fileName}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - 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); + 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); @Put("{shareName}/{directory}/{fileName}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - 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); + 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); @Put("{shareName}/{directory}/{fileName}") @ExpectedResponses({201}) @UnexpectedResponseExceptionType(StorageErrorException.class) - 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); + 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); @Get("{shareName}/{directory}/{fileName}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - 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); + 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); @Put("{shareName}/{directory}/{fileName}") @ExpectedResponses({202}) @UnexpectedResponseExceptionType(StorageErrorException.class) - 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); + 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); @Put("{shareName}/{directory}/{fileName}") @ExpectedResponses({204}) @UnexpectedResponseExceptionType(StorageErrorException.class) - 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); + 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); @Get("{shareName}/{directory}/{fileName}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - 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); + 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); @Put("{shareName}/{directory}/{fileName}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - 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); + 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); } /** * 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. @@ -155,14 +152,12 @@ public Mono createWithRestResponseAsync(long fileContentLen final String fileCacheControl = null; final String fileContentDisposition = null; String fileContentMD5Converted = null; - return service.create(this.client.url(), shareName, filePath, timeout, this.client.version(), fileContentLength, fileTypeConstant, metadata, fileContentType, fileContentEncoding, fileContentLanguage, fileCacheControl, fileContentMD5Converted, fileContentDisposition, context); + return service.create(this.client.url(), 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. @@ -199,14 +194,12 @@ public Mono createWithRestResponseAsync(long fileContentLen fileContentDisposition = fileHTTPHeaders.fileContentDisposition(); } String fileContentMD5Converted = Base64Util.encodeToString(fileContentMD5); - return service.create(this.client.url(), shareName, filePath, timeout, this.client.version(), fileContentLength, fileTypeConstant, metadata, fileContentType, fileContentEncoding, fileContentLanguage, fileCacheControl, fileContentMD5Converted, fileContentDisposition, context); + return service.create(this.client.url(), 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. @@ -216,14 +209,12 @@ public Mono downloadWithRestResponseAsync(Context context final Integer timeout = null; final String range = null; final Boolean rangeGetContentMD5 = null; - return service.download(this.client.url(), shareName, filePath, timeout, this.client.version(), range, rangeGetContentMD5, context); + return service.download(this.client.url(), 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. @@ -239,8 +230,6 @@ public Mono downloadWithRestResponseAsync(Integer timeout /** * 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. @@ -249,14 +238,12 @@ public Mono downloadWithRestResponseAsync(Integer timeout public Mono getPropertiesWithRestResponseAsync(Context context) { final String sharesnapshot = null; final Integer timeout = null; - return service.getProperties(this.client.url(), shareName, filePath, sharesnapshot, timeout, this.client.version(), context); + return service.getProperties(this.client.url(), 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. @@ -271,8 +258,6 @@ public Mono getPropertiesWithRestResponseAsync(Strin /** * 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. @@ -280,14 +265,12 @@ public Mono getPropertiesWithRestResponseAsync(Strin @ServiceMethod(returns = ReturnType.SINGLE) public Mono deleteWithRestResponseAsync(Context context) { final Integer timeout = null; - return service.delete(this.client.url(), shareName, filePath, timeout, this.client.version(), context); + return service.delete(this.client.url(), 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. @@ -301,8 +284,6 @@ public Mono deleteWithRestResponseAsync(Integer timeout, Co /** * 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. @@ -318,14 +299,12 @@ public Mono setHTTPHeadersWithRestResponseAsync(Con final String fileCacheControl = null; final String fileContentDisposition = null; String fileContentMD5Converted = null; - return service.setHTTPHeaders(this.client.url(), shareName, filePath, timeout, this.client.version(), fileContentLength, comp, fileContentType, fileContentEncoding, fileContentLanguage, fileCacheControl, fileContentMD5Converted, fileContentDisposition, context); + return service.setHTTPHeaders(this.client.url(), 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. @@ -361,14 +340,12 @@ public Mono setHTTPHeadersWithRestResponseAsync(Int fileContentDisposition = fileHTTPHeaders.fileContentDisposition(); } String fileContentMD5Converted = Base64Util.encodeToString(fileContentMD5); - return service.setHTTPHeaders(this.client.url(), shareName, filePath, timeout, this.client.version(), fileContentLength, comp, fileContentType, fileContentEncoding, fileContentLanguage, fileCacheControl, fileContentMD5Converted, fileContentDisposition, context); + return service.setHTTPHeaders(this.client.url(), 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. @@ -378,14 +355,12 @@ public Mono setMetadataWithRestResponseAsync(Context c final Integer timeout = null; final Map metadata = null; final String comp = "metadata"; - return service.setMetadata(this.client.url(), shareName, filePath, timeout, metadata, this.client.version(), comp, context); + return service.setMetadata(this.client.url(), 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. @@ -395,14 +370,12 @@ public Mono setMetadataWithRestResponseAsync(Context c @ServiceMethod(returns = ReturnType.SINGLE) public Mono setMetadataWithRestResponseAsync(Integer timeout, Map metadata, Context context) { final String comp = "metadata"; - return service.setMetadata(this.client.url(), shareName, filePath, timeout, metadata, this.client.version(), comp, context); + return service.setMetadata(this.client.url(), 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. @@ -416,14 +389,12 @@ public Mono uploadRangeWithRestResponseAsync(String ra final Integer timeout = null; final String comp = "range"; String contentMD5Converted = null; - return service.uploadRange(this.client.url(), shareName, filePath, optionalbody, timeout, range, fileRangeWrite, contentLength, contentMD5Converted, this.client.version(), comp, context); + return service.uploadRange(this.client.url(), 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. @@ -438,14 +409,12 @@ public Mono uploadRangeWithRestResponseAsync(String ra public Mono uploadRangeWithRestResponseAsync(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(), shareName, filePath, optionalbody, timeout, range, fileRangeWrite, contentLength, contentMD5Converted, this.client.version(), comp, context); + return service.uploadRange(this.client.url(), 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. @@ -456,14 +425,12 @@ public Mono getRangeListWithRestResponseAsync(Context final Integer timeout = null; final String range = null; final String comp = "rangelist"; - return service.getRangeList(this.client.url(), shareName, filePath, sharesnapshot, timeout, this.client.version(), range, comp, context); + return service.getRangeList(this.client.url(), 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. @@ -474,14 +441,12 @@ public Mono getRangeListWithRestResponseAsync(Context @ServiceMethod(returns = ReturnType.SINGLE) public Mono getRangeListWithRestResponseAsync(String sharesnapshot, Integer timeout, String range, Context context) { final String comp = "rangelist"; - return service.getRangeList(this.client.url(), shareName, filePath, sharesnapshot, timeout, this.client.version(), range, comp, context); + return service.getRangeList(this.client.url(), 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. @@ -491,14 +456,12 @@ public Mono getRangeListWithRestResponseAsync(String public Mono startCopyWithRestResponseAsync(String copySource, Context context) { final Integer timeout = null; final Map metadata = null; - return service.startCopy(this.client.url(), shareName, filePath, timeout, this.client.version(), metadata, copySource, context); + return service.startCopy(this.client.url(), 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. @@ -514,8 +477,6 @@ public Mono startCopyWithRestResponseAsync(String copySo /** * 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. @@ -526,14 +487,12 @@ public Mono abortCopyWithRestResponseAsync(String copyId final Integer timeout = null; final String copyActionAbortConstant = "abort"; final String comp = "copy"; - return service.abortCopy(this.client.url(), shareName, filePath, copyId, timeout, copyActionAbortConstant, this.client.version(), comp, context); + return service.abortCopy(this.client.url(), 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. @@ -544,14 +503,12 @@ public Mono abortCopyWithRestResponseAsync(String copyId public Mono abortCopyWithRestResponseAsync(String copyId, Integer timeout, Context context) { final String copyActionAbortConstant = "abort"; final String comp = "copy"; - return service.abortCopy(this.client.url(), shareName, filePath, copyId, timeout, copyActionAbortConstant, this.client.version(), comp, context); + return service.abortCopy(this.client.url(), 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. @@ -563,14 +520,12 @@ public Mono listHandlesWithRestResponseAsync(Context c final Integer timeout = null; final String sharesnapshot = null; final String comp = "listhandles"; - return service.listHandles(this.client.url(), shareName, filePath, marker, maxresults, timeout, sharesnapshot, this.client.version(), comp, context); + return service.listHandles(this.client.url(), 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>. @@ -582,14 +537,12 @@ public Mono listHandlesWithRestResponseAsync(Context c @ServiceMethod(returns = ReturnType.SINGLE) public Mono listHandlesWithRestResponseAsync(String marker, Integer maxresults, Integer timeout, String sharesnapshot, Context context) { final String comp = "listhandles"; - return service.listHandles(this.client.url(), shareName, filePath, marker, maxresults, timeout, sharesnapshot, this.client.version(), comp, context); + return service.listHandles(this.client.url(), 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. @@ -601,14 +554,12 @@ public Mono forceCloseHandlesWithRestResponseAsy final String marker = null; final String sharesnapshot = null; final String comp = "forceclosehandles"; - return service.forceCloseHandles(this.client.url(), shareName, filePath, timeout, marker, sharesnapshot, handleId, this.client.version(), comp, context); + return service.forceCloseHandles(this.client.url(), 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. @@ -620,6 +571,6 @@ public Mono forceCloseHandlesWithRestResponseAsy @ServiceMethod(returns = ReturnType.SINGLE) public Mono forceCloseHandlesWithRestResponseAsync(String handleId, Integer timeout, String marker, String sharesnapshot, Context context) { final String comp = "forceclosehandles"; - return service.forceCloseHandles(this.client.url(), shareName, filePath, timeout, marker, sharesnapshot, handleId, this.client.version(), comp, context); + return service.forceCloseHandles(this.client.url(), 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 b176e74b2a1cd..b83b5490bc131 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 @@ -20,7 +20,6 @@ import com.azure.core.implementation.annotation.UnexpectedResponseExceptionType; 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; @@ -65,7 +64,7 @@ private interface ServicesService { @Put("") @ExpectedResponses({202}) @UnexpectedResponseExceptionType(StorageErrorException.class) - 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); + 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); @Get("") @ExpectedResponses({200}) @@ -81,7 +80,7 @@ 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 fileServiceProperties The FileService properties. + * @param storageServiceProperties The StorageService 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. @@ -91,13 +90,13 @@ public Mono setPropertiesWithRestResponseAsync(St final Integer timeout = null; final String restype = "service"; final String comp = "properties"; - return service.setProperties(this.client.url(), fileServiceProperties, timeout, this.client.version(), restype, comp, context); + return service.setProperties(this.client.url(), storageServiceProperties, 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 fileServiceProperties The FileService properties. + * @param storageServiceProperties The StorageService 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. @@ -107,7 +106,7 @@ public Mono setPropertiesWithRestResponseAsync(St public Mono setPropertiesWithRestResponseAsync(StorageServiceProperties storageServiceProperties, Integer timeout, Context context) { final String restype = "service"; final String comp = "properties"; - return service.setProperties(this.client.url(), fileServiceProperties, timeout, this.client.version(), restype, comp, context); + return service.setProperties(this.client.url(), storageServiceProperties, 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 48f13331c3537..a0a3758a23da6 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 @@ -32,7 +32,6 @@ import com.azure.storage.file.models.SignedIdentifier; import com.azure.storage.file.models.StorageErrorException; import java.util.List; -import reactor.core.publisher.Mono; import java.util.Map; import reactor.core.publisher.Mono; @@ -76,17 +75,17 @@ private interface SharesService { @Get("{shareName}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - 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); + 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); @Delete("{shareName}") @ExpectedResponses({202}) @UnexpectedResponseExceptionType(StorageErrorException.class) - 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); + 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); @Put("{shareName}") @ExpectedResponses({201}) @UnexpectedResponseExceptionType(StorageErrorException.class) - 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); + 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); @Put("{shareName}") @ExpectedResponses({200}) @@ -96,28 +95,27 @@ private interface SharesService { @Put("{shareName}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - 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); + 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); @Get("{shareName}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - 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); + 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); @Put("{shareName}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - 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); + 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); @Get("{shareName}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - 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); + 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); } /** * 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. @@ -128,13 +126,12 @@ public Mono createWithRestResponseAsync(Context context) { final Map metadata = null; final Long quota = null; final String restype = "share"; - return service.create(this.client.url(), shareName, timeout, metadata, quota, this.client.version(), restype, context); + return service.create(this.client.url(), 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. @@ -145,13 +142,12 @@ public Mono createWithRestResponseAsync(Context context) { @ServiceMethod(returns = ReturnType.SINGLE) public Mono createWithRestResponseAsync(Integer timeout, Map metadata, Long quota, Context context) { final String restype = "share"; - return service.create(this.client.url(), shareName, timeout, metadata, quota, this.client.version(), restype, context); + return service.create(this.client.url(), 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. @@ -161,13 +157,12 @@ public Mono getPropertiesWithRestResponseAsync(Cont final String sharesnapshot = null; final Integer timeout = null; final String restype = "share"; - return service.getProperties(this.client.url(), shareName, sharesnapshot, timeout, this.client.version(), restype, context); + return service.getProperties(this.client.url(), 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. @@ -177,13 +172,12 @@ public Mono getPropertiesWithRestResponseAsync(Cont @ServiceMethod(returns = ReturnType.SINGLE) public Mono getPropertiesWithRestResponseAsync(String sharesnapshot, Integer timeout, Context context) { final String restype = "share"; - return service.getProperties(this.client.url(), shareName, sharesnapshot, timeout, this.client.version(), restype, context); + return service.getProperties(this.client.url(), 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. @@ -194,13 +188,12 @@ public Mono deleteWithRestResponseAsync(Context context) { final Integer timeout = null; final DeleteSnapshotsOptionType deleteSnapshots = null; final String restype = "share"; - return service.delete(this.client.url(), shareName, sharesnapshot, timeout, this.client.version(), deleteSnapshots, restype, context); + return service.delete(this.client.url(), 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'. @@ -211,13 +204,12 @@ public Mono deleteWithRestResponseAsync(Context context) { @ServiceMethod(returns = ReturnType.SINGLE) public Mono deleteWithRestResponseAsync(String sharesnapshot, Integer timeout, DeleteSnapshotsOptionType deleteSnapshots, Context context) { final String restype = "share"; - return service.delete(this.client.url(), shareName, sharesnapshot, timeout, this.client.version(), deleteSnapshots, restype, context); + return service.delete(this.client.url(), 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. @@ -228,13 +220,12 @@ public Mono createSnapshotWithRestResponseAsync(Co final Map metadata = null; final String restype = "share"; final String comp = "snapshot"; - return service.createSnapshot(this.client.url(), shareName, timeout, metadata, this.client.version(), restype, comp, context); + return service.createSnapshot(this.client.url(), 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. @@ -245,13 +236,12 @@ public Mono createSnapshotWithRestResponseAsync(Co public Mono createSnapshotWithRestResponseAsync(Integer timeout, Map metadata, Context context) { final String restype = "share"; final String comp = "snapshot"; - return service.createSnapshot(this.client.url(), shareName, timeout, metadata, this.client.version(), restype, comp, context); + return service.createSnapshot(this.client.url(), 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. @@ -262,13 +252,12 @@ public Mono setQuotaWithRestResponseAsync(Context contex final Long quota = null; final String restype = "share"; final String comp = "properties"; - return service.setQuota(this.client.url(), shareName, timeout, this.client.version(), quota, restype, comp, context); + return service.setQuota(this.client.url(), 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. @@ -279,13 +268,12 @@ public Mono setQuotaWithRestResponseAsync(Context contex public Mono setQuotaWithRestResponseAsync(Integer timeout, Long quota, Context context) { final String restype = "share"; final String comp = "properties"; - return service.setQuota(this.client.url(), shareName, timeout, this.client.version(), quota, restype, comp, context); + return service.setQuota(this.client.url(), 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. @@ -296,13 +284,12 @@ public Mono setMetadataWithRestResponseAsync(Context final Map metadata = null; final String restype = "share"; final String comp = "metadata"; - return service.setMetadata(this.client.url(), shareName, timeout, metadata, this.client.version(), restype, comp, context); + return service.setMetadata(this.client.url(), 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. @@ -313,13 +300,12 @@ public Mono setMetadataWithRestResponseAsync(Context public Mono setMetadataWithRestResponseAsync(Integer timeout, Map metadata, Context context) { final String restype = "share"; final String comp = "metadata"; - return service.setMetadata(this.client.url(), shareName, timeout, metadata, this.client.version(), restype, comp, context); + return service.setMetadata(this.client.url(), 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. @@ -329,13 +315,12 @@ public Mono getAccessPolicyWithRestResponseAsync( final Integer timeout = null; final String restype = "share"; final String comp = "acl"; - return service.getAccessPolicy(this.client.url(), shareName, timeout, this.client.version(), restype, comp, context); + return service.getAccessPolicy(this.client.url(), 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. @@ -345,13 +330,12 @@ public Mono getAccessPolicyWithRestResponseAsync( public Mono getAccessPolicyWithRestResponseAsync(Integer timeout, Context context) { final String restype = "share"; final String comp = "acl"; - return service.getAccessPolicy(this.client.url(), shareName, timeout, this.client.version(), restype, comp, context); + return service.getAccessPolicy(this.client.url(), 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. @@ -362,13 +346,12 @@ public Mono setAccessPolicyWithRestResponseAsync( final String restype = "share"; final String comp = "acl"; SignedIdentifiersWrapper shareAclConverted = new SignedIdentifiersWrapper(null); - return service.setAccessPolicy(this.client.url(), shareName, shareAclConverted, timeout, this.client.version(), restype, comp, context); + return service.setAccessPolicy(this.client.url(), 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. @@ -380,13 +363,12 @@ public Mono setAccessPolicyWithRestResponseAsync( final String restype = "share"; final String comp = "acl"; SignedIdentifiersWrapper shareAclConverted = new SignedIdentifiersWrapper(shareAcl); - return service.setAccessPolicy(this.client.url(), shareName, shareAclConverted, timeout, this.client.version(), restype, comp, context); + return service.setAccessPolicy(this.client.url(), 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. @@ -396,13 +378,12 @@ public Mono getStatisticsWithRestResponseAsync(Cont final Integer timeout = null; final String restype = "share"; final String comp = "stats"; - return service.getStatistics(this.client.url(), shareName, timeout, this.client.version(), restype, comp, context); + return service.getStatistics(this.client.url(), 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. @@ -412,6 +393,6 @@ public Mono getStatisticsWithRestResponseAsync(Cont public Mono getStatisticsWithRestResponseAsync(Integer timeout, Context context) { final String restype = "share"; final String comp = "stats"; - return service.getStatistics(this.client.url(), shareName, timeout, this.client.version(), restype, comp, context); + return service.getStatistics(this.client.url(), timeout, this.client.version(), restype, comp, context); } } 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 76fb6e22ea5f8..a1b837aec2516 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 @@ -28,7 +28,7 @@ public final class ListFilesAndDirectoriesSegmentResponse { private String shareName; /* - * The snapshot property. + * The shareSnapshot property. */ @JacksonXmlProperty(localName = "ShareSnapshot", isAttribute = true) private String shareSnapshot; @@ -110,18 +110,18 @@ public ListFilesAndDirectoriesSegmentResponse shareName(String shareName) { } /** - * Get the snapshot property: The snapshot property. + * Get the shareSnapshot property: The shareSnapshot property. * - * @return the snapshot value. + * @return the shareSnapshot value. */ public String shareSnapshot() { return this.shareSnapshot; } /** - * Set the snapshot property: The snapshot property. + * Set the shareSnapshot property: The shareSnapshot property. * - * @param shareSnapshot the snapshot value to set. + * @param shareSnapshot the shareSnapshot 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/ServicesGetPropertiesResponse.java b/storage/client/file/src/main/java/com/azure/storage/file/models/ServicesGetPropertiesResponse.java index 92a15ab7d889e..267a198ab8b8d 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. * @@ -106,13 +100,4 @@ public ShareProperties quota(long 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/queue/src/main/java/com/azure/storage/queue/implementation/AzureQueueStorageBuilder.java b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/AzureQueueStorageBuilder.java index 54408f095739f..b8fc2de79856e 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/AzureQueueStorageBuilder.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/AzureQueueStorageBuilder.java @@ -77,7 +77,9 @@ public AzureQueueStorageImpl build() { if (this.url != null) { client.url(this.url); } - client.version(this.version); + if (this.version != null) { + client.version(this.version); + } return client; } } diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessageIdsImpl.java b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessageIdsImpl.java index c6a129166cb8f..1b95a0982419f 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessageIdsImpl.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessageIdsImpl.java @@ -59,12 +59,12 @@ private interface MessageIdsService { @Put("{queueName}/messages/{messageid}") @ExpectedResponses({204}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono update(@HostParam("url") String url, @PathParam("queueName") String queueName, @PathParam("messageid") String messageId, @BodyParam("application/xml; charset=utf-8") QueueMessage queueMessage, @QueryParam("popreceipt") String popReceipt, @QueryParam("visibilitytimeout") int visibilitytimeout, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context); + Mono update(@HostParam("url") String url, @BodyParam("application/xml; charset=utf-8") QueueMessage queueMessage, @QueryParam("popreceipt") String popReceipt, @QueryParam("visibilitytimeout") int visibilitytimeout, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context); @Delete("{queueName}/messages/{messageid}") @ExpectedResponses({204}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono delete(@HostParam("url") String url, @PathParam("queueName") String queueName, @PathParam("messageid") String messageId, @QueryParam("popreceipt") String popReceipt, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context); + Mono delete(@HostParam("url") String url, @QueryParam("popreceipt") String popReceipt, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context); } /** @@ -81,7 +81,7 @@ private interface MessageIdsService { public Mono updateWithRestResponseAsync(QueueMessage queueMessage, String popReceipt, int visibilitytimeout, Context context) { final Integer timeout = null; final String requestId = null; - return service.update(this.client.url(), queueName, messageId, queueMessage, popReceipt, visibilitytimeout, timeout, this.client.version(), requestId, context); + return service.update(this.client.url(), queueMessage, popReceipt, visibilitytimeout, timeout, this.client.version(), requestId, context); } /** @@ -113,7 +113,7 @@ public Mono updateWithRestResponseAsync(QueueMessage q public Mono deleteWithRestResponseAsync(String popReceipt, Context context) { final Integer timeout = null; final String requestId = null; - return service.delete(this.client.url(), queueName, messageId, popReceipt, timeout, this.client.version(), requestId, context); + return service.delete(this.client.url(), popReceipt, timeout, this.client.version(), requestId, context); } /** diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessagesImpl.java b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessagesImpl.java index 92e50ce908a9d..b7815e46867e4 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessagesImpl.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessagesImpl.java @@ -62,22 +62,22 @@ private interface MessagesService { @Get("{queueName}/messages") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono dequeue(@HostParam("url") String url, @PathParam("queueName") String queueName, @QueryParam("numofmessages") Integer numberOfMessages, @QueryParam("visibilitytimeout") Integer visibilitytimeout, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context); + Mono dequeue(@HostParam("url") String url, @QueryParam("numofmessages") Integer numberOfMessages, @QueryParam("visibilitytimeout") Integer visibilitytimeout, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context); @Delete("{queueName}/messages") @ExpectedResponses({204}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono clear(@HostParam("url") String url, @PathParam("queueName") String queueName, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context); + Mono clear(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context); @Post("{queueName}/messages") @ExpectedResponses({201}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono enqueue(@HostParam("url") String url, @PathParam("queueName") String queueName, @BodyParam("application/xml; charset=utf-8") QueueMessage queueMessage, @QueryParam("visibilitytimeout") Integer visibilitytimeout, @QueryParam("messagettl") Integer messageTimeToLive, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context); + Mono enqueue(@HostParam("url") String url, @BodyParam("application/xml; charset=utf-8") QueueMessage queueMessage, @QueryParam("visibilitytimeout") Integer visibilitytimeout, @QueryParam("messagettl") Integer messageTimeToLive, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context); @Get("{queueName}/messages") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono peek(@HostParam("url") String url, @PathParam("queueName") String queueName, @QueryParam("numofmessages") Integer numberOfMessages, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("peekonly") String peekonly, Context context); + Mono peek(@HostParam("url") String url, @QueryParam("numofmessages") Integer numberOfMessages, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("peekonly") String peekonly, Context context); } /** @@ -93,7 +93,7 @@ public Mono dequeueWithRestResponseAsync(Context contex final Integer visibilitytimeout = null; final Integer timeout = null; final String requestId = null; - return service.dequeue(this.client.url(), queueName, numberOfMessages, visibilitytimeout, timeout, this.client.version(), requestId, context); + return service.dequeue(this.client.url(), numberOfMessages, visibilitytimeout, timeout, this.client.version(), requestId, context); } /** @@ -123,7 +123,7 @@ public Mono dequeueWithRestResponseAsync(Integer number public Mono clearWithRestResponseAsync(Context context) { final Integer timeout = null; final String requestId = null; - return service.clear(this.client.url(), queueName, timeout, this.client.version(), requestId, context); + return service.clear(this.client.url(), timeout, this.client.version(), requestId, context); } /** @@ -154,7 +154,7 @@ public Mono enqueueWithRestResponseAsync(QueueMessage q final Integer messageTimeToLive = null; final Integer timeout = null; final String requestId = null; - return service.enqueue(this.client.url(), queueName, queueMessage, visibilitytimeout, messageTimeToLive, timeout, this.client.version(), requestId, context); + return service.enqueue(this.client.url(), queueMessage, visibilitytimeout, messageTimeToLive, timeout, this.client.version(), requestId, context); } /** @@ -187,7 +187,7 @@ public Mono peekWithRestResponseAsync(Context context) { final Integer timeout = null; final String requestId = null; final String peekonly = "true"; - return service.peek(this.client.url(), queueName, numberOfMessages, timeout, this.client.version(), requestId, peekonly, context); + return service.peek(this.client.url(), numberOfMessages, timeout, this.client.version(), requestId, peekonly, context); } /** @@ -203,6 +203,6 @@ public Mono peekWithRestResponseAsync(Context context) { @ServiceMethod(returns = ReturnType.SINGLE) public Mono peekWithRestResponseAsync(Integer numberOfMessages, Integer timeout, String requestId, Context context) { final String peekonly = "true"; - return service.peek(this.client.url(), queueName, numberOfMessages, timeout, this.client.version(), requestId, peekonly, context); + return service.peek(this.client.url(), numberOfMessages, timeout, this.client.version(), requestId, peekonly, context); } } diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/QueuesImpl.java b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/QueuesImpl.java index 0152aeb2d4027..f498f6c4d3955 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/QueuesImpl.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/QueuesImpl.java @@ -66,32 +66,32 @@ private interface QueuesService { @Put("{queueName}") @ExpectedResponses({201, 204}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono create(@HostParam("url") String url, @PathParam("queueName") String queueName, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-meta-") Map metadata, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context); + Mono create(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-meta-") Map metadata, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context); @Delete("{queueName}") @ExpectedResponses({204}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono delete(@HostParam("url") String url, @PathParam("queueName") String queueName, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context); + Mono delete(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context); @Get("{queueName}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono getProperties(@HostParam("url") String url, @PathParam("queueName") String queueName, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, Context context); + Mono getProperties(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, Context context); @Put("{queueName}") @ExpectedResponses({204}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono setMetadata(@HostParam("url") String url, @PathParam("queueName") String queueName, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-meta-") Map metadata, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, Context context); + Mono setMetadata(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-meta-") Map metadata, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, Context context); @Get("{queueName}") @ExpectedResponses({200}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono getAccessPolicy(@HostParam("url") String url, @PathParam("queueName") String queueName, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, Context context); + Mono getAccessPolicy(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, Context context); @Put("{queueName}") @ExpectedResponses({204}) @UnexpectedResponseExceptionType(StorageErrorException.class) - Mono setAccessPolicy(@HostParam("url") String url, @PathParam("queueName") String queueName, @BodyParam("application/xml; charset=utf-8") SignedIdentifiersWrapper queueAcl, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, Context context); + Mono setAccessPolicy(@HostParam("url") String url, @BodyParam("application/xml; charset=utf-8") SignedIdentifiersWrapper queueAcl, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, Context context); } /** @@ -106,7 +106,7 @@ public Mono createWithRestResponseAsync(Context context) { final Integer timeout = null; final Map metadata = null; final String requestId = null; - return service.create(this.client.url(), queueName, timeout, metadata, this.client.version(), requestId, context); + return service.create(this.client.url(), timeout, metadata, this.client.version(), requestId, context); } /** @@ -135,7 +135,7 @@ public Mono createWithRestResponseAsync(Integer timeout, M public Mono deleteWithRestResponseAsync(Context context) { final Integer timeout = null; final String requestId = null; - return service.delete(this.client.url(), queueName, timeout, this.client.version(), requestId, context); + return service.delete(this.client.url(), timeout, this.client.version(), requestId, context); } /** @@ -164,7 +164,7 @@ public Mono getPropertiesWithRestResponseAsync(Cont final Integer timeout = null; final String requestId = null; final String comp = "metadata"; - return service.getProperties(this.client.url(), queueName, timeout, this.client.version(), requestId, comp, context); + return service.getProperties(this.client.url(), timeout, this.client.version(), requestId, comp, context); } /** @@ -179,7 +179,7 @@ public Mono getPropertiesWithRestResponseAsync(Cont @ServiceMethod(returns = ReturnType.SINGLE) public Mono getPropertiesWithRestResponseAsync(Integer timeout, String requestId, Context context) { final String comp = "metadata"; - return service.getProperties(this.client.url(), queueName, timeout, this.client.version(), requestId, comp, context); + return service.getProperties(this.client.url(), timeout, this.client.version(), requestId, comp, context); } /** @@ -195,7 +195,7 @@ public Mono setMetadataWithRestResponseAsync(Context final Map metadata = null; final String requestId = null; final String comp = "metadata"; - return service.setMetadata(this.client.url(), queueName, timeout, metadata, this.client.version(), requestId, comp, context); + return service.setMetadata(this.client.url(), timeout, metadata, this.client.version(), requestId, comp, context); } /** @@ -211,7 +211,7 @@ public Mono setMetadataWithRestResponseAsync(Context @ServiceMethod(returns = ReturnType.SINGLE) public Mono setMetadataWithRestResponseAsync(Integer timeout, Map metadata, String requestId, Context context) { final String comp = "metadata"; - return service.setMetadata(this.client.url(), queueName, timeout, metadata, this.client.version(), requestId, comp, context); + return service.setMetadata(this.client.url(), timeout, metadata, this.client.version(), requestId, comp, context); } /** @@ -226,7 +226,7 @@ public Mono getAccessPolicyWithRestResponseAsync( final Integer timeout = null; final String requestId = null; final String comp = "acl"; - return service.getAccessPolicy(this.client.url(), queueName, timeout, this.client.version(), requestId, comp, context); + return service.getAccessPolicy(this.client.url(), timeout, this.client.version(), requestId, comp, context); } /** @@ -241,7 +241,7 @@ public Mono getAccessPolicyWithRestResponseAsync( @ServiceMethod(returns = ReturnType.SINGLE) public Mono getAccessPolicyWithRestResponseAsync(Integer timeout, String requestId, Context context) { final String comp = "acl"; - return service.getAccessPolicy(this.client.url(), queueName, timeout, this.client.version(), requestId, comp, context); + return service.getAccessPolicy(this.client.url(), timeout, this.client.version(), requestId, comp, context); } /** @@ -257,7 +257,7 @@ public Mono setAccessPolicyWithRestResponseAsync( final String requestId = null; final String comp = "acl"; SignedIdentifiersWrapper queueAclConverted = new SignedIdentifiersWrapper(null); - return service.setAccessPolicy(this.client.url(), queueName, queueAclConverted, timeout, this.client.version(), requestId, comp, context); + return service.setAccessPolicy(this.client.url(), queueAclConverted, timeout, this.client.version(), requestId, comp, context); } /** @@ -274,6 +274,6 @@ public Mono setAccessPolicyWithRestResponseAsync( public Mono setAccessPolicyWithRestResponseAsync(List queueAcl, Integer timeout, String requestId, Context context) { final String comp = "acl"; SignedIdentifiersWrapper queueAclConverted = new SignedIdentifiersWrapper(queueAcl); - return service.setAccessPolicy(this.client.url(), queueName, queueAclConverted, timeout, this.client.version(), requestId, comp, context); + return service.setAccessPolicy(this.client.url(), queueAclConverted, timeout, this.client.version(), requestId, comp, context); } } diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/DequeuedMessage.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/DequeuedMessage.java index 65e6e941c717a..81614fc1cba98 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/DequeuedMessage.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/DequeuedMessage.java @@ -1,9 +1,11 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +// Code generated by Microsoft (R) AutoRest Code Generator. package com.azure.storage.queue.models; import com.azure.core.implementation.DateTimeRfc1123; +import com.azure.core.implementation.annotation.Fluent; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.time.OffsetDateTime; @@ -13,6 +15,7 @@ * on a Queue. */ @JacksonXmlRootElement(localName = "QueueMessage") +@Fluent public final class DequeuedMessage { /* * The Id of the Message. diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/PeekedMessage.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/PeekedMessage.java index 617e8f2f962c9..c8a3c26ab9738 100644 --- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/PeekedMessage.java +++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/PeekedMessage.java @@ -1,5 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +// Code generated by Microsoft (R) AutoRest Code Generator. package com.azure.storage.queue.models; @@ -15,7 +16,7 @@ */ @JacksonXmlRootElement(localName = "QueueMessage") @Fluent -public final class PeekedMessageItem { +public final class PeekedMessage { /* * The Id of the Message. */ From 7149824406f0af4eade4dd60c2a8bd7df1635ce1 Mon Sep 17 00:00:00 2001 From: Jianghao Lu Date: Wed, 24 Jul 2019 10:27:20 -0700 Subject: [PATCH 11/17] Up azure core version for file & queue --- storage/client/file/pom.xml | 4 ++-- storage/client/queue/pom.xml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/storage/client/file/pom.xml b/storage/client/file/pom.xml index 5355d42110408..c9fe47848dcf1 100644 --- a/storage/client/file/pom.xml +++ b/storage/client/file/pom.xml @@ -35,7 +35,7 @@ com.azure azure-core - 1.0.0-preview.2 + 1.0.0-preview.3 + @@ -445,6 +445,16 @@ + + + + + + + + +