From d85185f910253a025d7f1156dcc025325c36cab9 Mon Sep 17 00:00:00 2001 From: Alan Zimmer <48699787+alzimmermsft@users.noreply.github.com> Date: Fri, 2 Aug 2019 10:59:06 -0700 Subject: [PATCH] Migrate Additional V11 Test Classes (#4491) * Removed raw clients * Fixed PageBlob getRange and getRangeDiff, turned on all unit tests * Turned on more tests * Partial work for implementing and testing reliable download options * Storage SAS implementation (#4404) * SAS implementation * Fixed some minor formatting issues * Fixed checkstyle problems and test issue * Turned on download retry test * RetryTests migrated * Passing most of HelperTest * Fixing tests after merge * Remove RawClients from Blobs (#4375) Removes RawClients from Storage Blobs * DownloadResponseTest working * Fixed scoping for some classes, Checkstyle fixes * Fixing more unit tests * Fix Checkstyle issue * Move adding acount name into String.format * Additional move of adding account name into String.format * Fixed assertGenerateOK logic for SAS generation * Removed invalid import * Fixed method parameter ordering --- .../storage/blob/AccountSASPermission.java | 65 +- .../storage/blob/AccountSASResourceType.java | 27 +- .../azure/storage/blob/AccountSASService.java | 32 +- .../blob/AccountSASSignatureValues.java | 75 +- .../blob/AnonymousCredentialPolicy.java | 32 - .../azure/storage/blob/BlobClientBuilder.java | 2 - .../azure/storage/blob/BlobConfiguration.java | 4 +- .../azure/storage/blob/BlobOutputStream.java | 2 +- .../azure/storage/blob/BlobProperties.java | 14 +- .../azure/storage/blob/BlobSASPermission.java | 39 +- .../blob/BlobServiceClientBuilder.java | 2 - .../storage/blob/ContainerAsyncClient.java | 3 +- .../storage/blob/ContainerClientBuilder.java | 2 - .../storage/blob/ContainerProperties.java | 20 +- .../storage/blob/ContainerSASPermission.java | 46 +- .../storage/blob/DownloadAsyncResponse.java | 53 +- .../azure/storage/blob/DownloadResponse.java | 1 - .../azure/storage/blob/HTTPGetterInfo.java | 35 +- .../java/com/azure/storage/blob/IPRange.java | 22 +- .../azure/storage/blob/IProgressReceiver.java | 10 +- .../storage/blob/PageBlobAsyncClient.java | 13 +- .../azure/storage/blob/PageBlobClient.java | 17 +- .../azure/storage/blob/ProgressReporter.java | 69 +- .../com/azure/storage/blob/SASProtocol.java | 2 +- .../storage/blob/SASQueryParameters.java | 78 +- .../blob/ServiceSASSignatureValues.java | 162 ++-- .../blob/UnexpectedLengthException.java | 32 + .../blob/models/BlobHierarchyListSegment.java | 3 + .../azure/storage/blob/models/BlobRange.java | 7 +- .../common/policy/RequestRetryOptions.java | 104 +-- .../common/policy/RequestRetryPolicy.java | 157 ++-- .../BlobAsyncClientJavaDocCodeSnippets.java | 4 +- .../blob/BlobClientJavaDocCodeSnippets.java | 4 +- .../com/azure/storage/blob/APISpec.groovy | 72 +- .../com/azure/storage/blob/AadLoginTest.java | 31 - .../storage/blob/AppendBlobAPITest.groovy | 3 + .../com/azure/storage/blob/BlobAPITest.groovy | 106 +-- .../storage/blob/BlockBlobAPITest.groovy | 20 +- .../blob/DownloadResponseMockFlux.java | 214 +++++ .../storage/blob/DownloadResponseTest.groovy | 152 ++++ .../com/azure/storage/blob/HelperTest.groovy | 730 ++++++++++++++++++ .../com/azure/storage/blob/LargeFileTest.java | 54 -- .../azure/storage/blob/PageBlobAPITest.groovy | 100 +-- .../storage/blob/ProgressReporterTest.groovy | 109 +++ .../storage/blob/RequestRetryTestFactory.java | 430 +++++++++++ .../com/azure/storage/blob/RetryTest.groovy | 144 ++++ .../com/azure/storage/blob/SASTest.groovy | 151 ++-- 47 files changed, 2662 insertions(+), 792 deletions(-) delete mode 100644 sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/AnonymousCredentialPolicy.java create mode 100644 sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/UnexpectedLengthException.java delete mode 100644 sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/AadLoginTest.java create mode 100644 sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/DownloadResponseMockFlux.java create mode 100644 sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/DownloadResponseTest.groovy create mode 100644 sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/HelperTest.groovy delete mode 100644 sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/LargeFileTest.java create mode 100644 sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ProgressReporterTest.groovy create mode 100644 sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/RequestRetryTestFactory.java create mode 100644 sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/RetryTest.groovy diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/AccountSASPermission.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/AccountSASPermission.java index 11369aabed0d7..4af9f970ff647 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/AccountSASPermission.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/AccountSASPermission.java @@ -12,7 +12,7 @@ * {@link AccountSASSignatureValues} object. It is possible to construct the permissions string without this class, but * the order of the permissions is particular and this class guarantees correctness. */ -final class AccountSASPermission { +public final class AccountSASPermission { private boolean read; @@ -33,7 +33,7 @@ final class AccountSASPermission { /** * Initializes an {@code AccountSASPermission} object with all fields set to false. */ - private AccountSASPermission() { + public AccountSASPermission() { } /** @@ -85,14 +85,17 @@ public static AccountSASPermission parse(String permString) { } /** - * Permission to read resources and list queues and tables granted. + * @return the read permission status */ public boolean read() { return read; } /** - * Permission to read resources and list queues and tables granted. + * Sets the read permission status. + * + * @param read Permission status to set + * @return the updated AccountSASPermission object */ public AccountSASPermission read(boolean read) { this.read = read; @@ -100,14 +103,17 @@ public AccountSASPermission read(boolean read) { } /** - * Permission to add messages, table entities, and append to blobs granted. + * @return the add permission status */ public boolean add() { return add; } /** - * Permission to add messages, table entities, and append to blobs granted. + * Sets the add permission status. + * + * @param add Permission status to set + * @return the updated AccountSASPermission object */ public AccountSASPermission add(boolean add) { this.add = add; @@ -115,14 +121,17 @@ public AccountSASPermission add(boolean add) { } /** - * Permission to create blobs and files granted. + * @return the create permission status */ public boolean create() { return create; } /** - * Permission to create blobs and files granted. + * Sets the create permission status. + * + * @param create Permission status to set + * @return the updated AccountSASPermission object */ public AccountSASPermission create(boolean create) { this.create = create; @@ -130,14 +139,17 @@ public AccountSASPermission create(boolean create) { } /** - * Permission to write resources granted. + * @return the write permission status */ public boolean write() { return write; } /** - * Permission to write resources granted. + * Sets the write permission status. + * + * @param write Permission status to set + * @return the updated AccountSASPermission object */ public AccountSASPermission write(boolean write) { this.write = write; @@ -145,14 +157,17 @@ public AccountSASPermission write(boolean write) { } /** - * Permission to delete resources granted. + * @return the delete permission status */ public boolean delete() { return delete; } /** - * Permission to delete resources granted. + * Sets the delete permission status. + * + * @param delete Permission status to set + * @return the updated AccountSASPermission object */ public AccountSASPermission delete(boolean delete) { this.delete = delete; @@ -160,14 +175,18 @@ public AccountSASPermission delete(boolean delete) { } /** - * Permission to list blob containers, blobs, shares, directories, and files granted. + * @return the list permission status */ public boolean list() { return list; } /** - * Permission to list blob containers, blobs, shares, directories, and files granted. + * Sets the list permission status. This permission grants the ability to list blob containers, blobs, shares, + * directories, and files. + * + * @param list Permission status to set + * @return the updated AccountSASPermission object */ public AccountSASPermission list(boolean list) { this.list = list; @@ -175,14 +194,19 @@ public AccountSASPermission list(boolean list) { } /** - * Permissions to update messages and table entities granted. + * Returns the update permission status, it allows the update of queue message and tables. + * + * @return the update permission status */ public boolean update() { return update; } /** - * Permissions to update messages and table entities granted. + * Sets the update permission status, it allows the update of queue messages and tables. + * + * @param update Permission status to set + * @return the updated AccountSASPermission object */ public AccountSASPermission update(boolean update) { this.update = update; @@ -190,14 +214,19 @@ public AccountSASPermission update(boolean update) { } /** - * Permission to get and delete messages granted. + * Returns the process messages permission, this allows the retrieval and deletion of queue messages. + * + * @return the process messages permission status. */ public boolean processMessages() { return processMessages; } /** - * Permission to get and delete messages granted. + * Sets the process messages permission, this allows the retrieval and deletion of queue messages. + * + * @param processMessages Permission status to set + * @return the updated AccountSASPermission object */ public AccountSASPermission processMessages(boolean processMessages) { this.processMessages = processMessages; diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/AccountSASResourceType.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/AccountSASResourceType.java index 6fc53c1902937..a91abf9175011 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/AccountSASResourceType.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/AccountSASResourceType.java @@ -12,7 +12,7 @@ * {@link AccountSASSignatureValues} object. It is possible to construct the resources string without this class, but * the order of the resources is particular and this class guarantees correctness. */ -final class AccountSASResourceType { +public final class AccountSASResourceType { private boolean service; @@ -23,7 +23,7 @@ final class AccountSASResourceType { /** * Initializes an {@code AccountSASResourceType} object with all fields set to false. */ - private AccountSASResourceType() { + public AccountSASResourceType() { } /** @@ -61,14 +61,17 @@ public static AccountSASResourceType parse(String resourceTypesString) { } /** - * Permission to access service level APIs granted. + * @return the access status for service level APIs. */ public boolean service() { return service; } /** - * Permission to access service level APIs granted. + * Sets the access status for service level APIs. + * + * @param service Access status to set + * @return the updated AccountSASResourceType object. */ public AccountSASResourceType service(boolean service) { this.service = service; @@ -76,14 +79,18 @@ public AccountSASResourceType service(boolean service) { } /** - * Permission to access container level APIs (Blob Containers, Tables, Queues, File Shares) granted. + * @return the access status for container level APIs, this grants access to Blob Containers, Tables, Queues, + * and File Shares. */ public boolean container() { return container; } /** - * Permission to access container level APIs (Blob Containers, Tables, Queues, File Shares) granted. + * Sets the access status for container level APIs, this grants access to Blob Containers, Tables, Queues, and File Shares. + * + * @param container Access status to set + * @return the updated AccountSASResourceType object. */ public AccountSASResourceType container(boolean container) { this.container = container; @@ -91,14 +98,18 @@ public AccountSASResourceType container(boolean container) { } /** - * Permission to access object level APIs (Blobs, Table Entities, Queue Messages, Files) granted. + * @return the access status for object level APIs, this grants access to Blobs, Table Entities, Queue Messages, + * Files. */ public boolean object() { return object; } /** - * Permission to access object level APIs (Blobs, Table Entities, Queue Messages, Files) granted. + * Sets the access status for object level APIs, this grants access to Blobs, Table Entities, Queue Messages, Files. + * + * @param object Access status to set + * @return the updated AccountSASResourceType object. */ public AccountSASResourceType object(boolean object) { this.object = object; diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/AccountSASService.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/AccountSASService.java index 0f88ccb2203a9..9fbb9137bcbd6 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/AccountSASService.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/AccountSASService.java @@ -12,7 +12,7 @@ * {@link AccountSASSignatureValues} object. It is possible to construct the services string without this class, but * the order of the services is particular and this class guarantees correctness. */ -final class AccountSASService { +public final class AccountSASService { private boolean blob; @@ -25,7 +25,7 @@ final class AccountSASService { /** * Initializes an {@code AccountSASService} object with all fields set to false. */ - private AccountSASService() { + public AccountSASService() { } /** @@ -66,14 +66,17 @@ public static AccountSASService parse(String servicesString) { } /** - * Permission to access blob resources granted. + * @return the access status for blob resources. */ public boolean blob() { return blob; } /** - * Permission to access blob resources granted. + * Sets the access status for blob resources. + * + * @param blob Access status to set + * @return the updated AccountSASService object. */ public AccountSASService blob(boolean blob) { this.blob = blob; @@ -81,14 +84,17 @@ public AccountSASService blob(boolean blob) { } /** - * Permission to access file resources granted. + * @return the access status for file resources. */ public boolean file() { return file; } /** - * Permission to access file resources granted. + * Sets the access status for file resources. + * + * @param file Access status to set + * @return the updated AccountSASService object. */ public AccountSASService file(boolean file) { this.file = file; @@ -96,14 +102,17 @@ public AccountSASService file(boolean file) { } /** - * Permission to access queue resources granted. + * @return the access status for queue resources. */ public boolean queue() { return queue; } /** - * Permission to access queue resources granted. + * Sets the access status for queue resources. + * + * @param queue Access status to set + * @return the updated AccountSASService object. */ public AccountSASService queue(boolean queue) { this.queue = queue; @@ -111,14 +120,17 @@ public AccountSASService queue(boolean queue) { } /** - * Permission to access table resources granted. + * @return the access status for table resources. */ public boolean table() { return table; } /** - * Permission to access table resources granted. + * Sets the access status for table resources. + * + * @param table Access status to set + * @return the updated AccountSASService object. */ public AccountSASService table(boolean table) { this.table = table; diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/AccountSASSignatureValues.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/AccountSASSignatureValues.java index d60118d87b121..5d770a8112e96 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/AccountSASSignatureValues.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/AccountSASSignatureValues.java @@ -24,9 +24,9 @@ * here for further * descriptions of the parameters, 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=account_sas "Sample code for AccountSASSignatureValues")] \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) + *
Please see + * here + * for additional samples.
*/ final class AccountSASSignatureValues { @@ -54,14 +54,19 @@ final class AccountSASSignatureValues { } /** - * If null or empty, this defaults to the service version targeted by this version of the library. + * @return the service version that is targeted, if {@code null} or empty the service version targeted by the + * library will be used. */ public String version() { return version; } /** - * If null or empty, this defaults to the service version targeted by this version of the library. + * Sets the service version that is targeted. Leave this {@code null} or empty to target the version used by the + * library. + * + * @param version Target version to set + * @return the updated AccountSASSignatureValues object. */ public AccountSASSignatureValues version(String version) { this.version = version; @@ -69,14 +74,17 @@ public AccountSASSignatureValues version(String version) { } /** - * {@link SASProtocol} + * @return the {@link SASProtocol} which determines the HTTP protocol that will be used. */ public SASProtocol protocol() { return protocol; } /** - * {@link SASProtocol} + * Sets the {@link SASProtocol} which determines the HTTP protocol that will be used. + * + * @param protocol Protocol to set + * @return the updated AccountSASSignatureValues object. */ public AccountSASSignatureValues protocol(SASProtocol protocol) { this.protocol = protocol; @@ -84,14 +92,17 @@ public AccountSASSignatureValues protocol(SASProtocol protocol) { } /** - * When the SAS will take effect. + * @return when the SAS will take effect. */ public OffsetDateTime startTime() { return startTime; } /** - * When the SAS will take effect. + * Sets when the SAS will take effect. + * + * @param startTime Start time to set + * @return the updated AccountSASSignatureValues object. */ public AccountSASSignatureValues startTime(OffsetDateTime startTime) { this.startTime = startTime; @@ -99,14 +110,17 @@ public AccountSASSignatureValues startTime(OffsetDateTime startTime) { } /** - * The time after which the SAS will no longer work. + * @return the time after which the SAS will no longer work. */ public OffsetDateTime expiryTime() { return expiryTime; } /** - * The time after which the SAS will no longer work. + * Sets the time after which the SAS will no longer work. + * + * @param expiryTime Expiry time to set + * @return the updated AccountSASSignatureValues object. */ public AccountSASSignatureValues expiryTime(OffsetDateTime expiryTime) { this.expiryTime = expiryTime; @@ -114,16 +128,19 @@ public AccountSASSignatureValues expiryTime(OffsetDateTime expiryTime) { } /** - * Specifies which operations the SAS user may perform. Please refer to {@link AccountSASPermission} for help - * constructing the permissions string. + * @return the operations the SAS user may perform. Please refer to {@link AccountSASPermission} to help determine + * which permissions are allowed. */ public String permissions() { return permissions; } /** - * Specifies which operations the SAS user may perform. Please refer to {@link AccountSASPermission} for help - * constructing the permissions string. + * Sets the operations the SAS user may perform. Please refer to {@link AccountSASPermission} for help constructing + * the permissions string. + * + * @param permissions Permissions string to set + * @return the updated AccountSASSignatureValues object. */ public AccountSASSignatureValues permissions(String permissions) { this.permissions = permissions; @@ -131,14 +148,17 @@ public AccountSASSignatureValues permissions(String permissions) { } /** - * {@link IPRange} + * @return the {@link IPRange} which determines the IP ranges that are allowed to use the SAS. */ public IPRange ipRange() { return ipRange; } /** - * {@link IPRange} + * Sets the {@link IPRange} which determines the IP ranges that are allowed to use the SAS. + * + * @param ipRange Allowed IP range to set + * @return the updated AccountSASSignatureValues object. */ public AccountSASSignatureValues ipRange(IPRange ipRange) { this.ipRange = ipRange; @@ -146,16 +166,18 @@ public AccountSASSignatureValues ipRange(IPRange ipRange) { } /** - * The values that indicate the services accessible with this SAS. Please refer to {@link AccountSASService} to - * construct this value. + * @return the services accessible with this SAS. Please refer to {@link AccountSASService} to help determine which + * services are accessible. */ public String services() { return services; } /** - * The values that indicate the services accessible with this SAS. Please refer to {@link AccountSASService} to - * construct this value. + * Sets the services accessible with this SAS. Please refer to {@link AccountSASService} to construct this value. + * + * @param services Allowed services string to set + * @return the updated AccountSASSignatureValues object. */ public AccountSASSignatureValues services(String services) { this.services = services; @@ -163,16 +185,19 @@ public AccountSASSignatureValues services(String services) { } /** - * The values that indicate the resource types accessible with this SAS. Please refer - * to {@link AccountSASResourceType} to construct this value. + * @return the resource types accessible with this SAS. Please refer to {@link AccountSASResourceType} to help + * determine the resource types that are accessible. */ public String resourceTypes() { return resourceTypes; } /** - * The values that indicate the resource types accessible with this SAS. Please refer - * to {@link AccountSASResourceType} to construct this value. + * Sets the resource types accessible with this SAS. Please refer to {@link AccountSASResourceType} to construct + * this value. + * + * @param resourceTypes Allowed resource types string to set + * @return the updated AccountSASSignatureValues object. */ public AccountSASSignatureValues resourceTypes(String resourceTypes) { this.resourceTypes = resourceTypes; diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/AnonymousCredentialPolicy.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/AnonymousCredentialPolicy.java deleted file mode 100644 index d5b1b30df030a..0000000000000 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/AnonymousCredentialPolicy.java +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.azure.storage.blob; - -import com.azure.core.http.HttpPipelineCallContext; -import com.azure.core.http.HttpPipelineNextPolicy; -import com.azure.core.http.HttpResponse; -import com.azure.core.http.policy.HttpPipelinePolicy; -import reactor.core.publisher.Mono; - -/** - * Anonymous credentials are to be used with with HTTP(S) requests that read blobs from public containers or requests - * that use a Shared Access Signature (SAS). This is because Anonymous credentials will not set an Authorization header. - * Pass an instance of this class as the credentials parameter when creating a new pipeline (typically with - * {@link BlobServiceClient}). - */ -public final class AnonymousCredentialPolicy implements HttpPipelinePolicy { - - /** - * Returns an empty instance of {@code AnonymousCredentials}. - */ - public AnonymousCredentialPolicy() { - } - - - - @Override - public MonoPlease see + * here + * for additional samples.
*/ final class ServiceSASSignatureValues { @@ -69,8 +69,8 @@ final class ServiceSASSignatureValues { /** * Creates an object with the specified expiry time and permissions * - * @param expiryTime - * @param permissions + * @param expiryTime Time the SAS becomes valid + * @param permissions Permissions granted by the SAS */ ServiceSASSignatureValues(OffsetDateTime expiryTime, String permissions) { this.expiryTime = expiryTime; @@ -80,7 +80,7 @@ final class ServiceSASSignatureValues { /** * Creates an object with the specified identifier * - * @param identifier + * @param identifier Identifier for the SAS */ ServiceSASSignatureValues(String identifier) { this.identifier = identifier; @@ -106,16 +106,19 @@ final class ServiceSASSignatureValues { } /** - * The version of the service this SAS will target. If not specified, it will default to the version targeted by the - * library. + * @return the version of the service this SAS will target. If not specified, it will default to the version targeted + * by the library. */ public String version() { return version; } /** - * The version of the service this SAS will target. If not specified, it will default to the version targeted by the - * library. + * Sets the version of the service this SAS will target. If not specified, it will default to the version targeted + * by the library. + * + * @param version Version to target + * @return the updated ServiceSASSignatureValues object */ public ServiceSASSignatureValues version(String version) { this.version = version; @@ -123,14 +126,17 @@ public ServiceSASSignatureValues version(String version) { } /** - * {@link SASProtocol} + * @return the {@link SASProtocol} which determines the protocols allowed by the SAS. */ public SASProtocol protocol() { return protocol; } /** - * {@link SASProtocol} + * Sets the {@link SASProtocol} which determines the protocols allowed by the SAS. + * + * @param protocol Protocol for the SAS + * @return the updated ServiceSASSignatureValues object */ public ServiceSASSignatureValues protocol(SASProtocol protocol) { this.protocol = protocol; @@ -138,14 +144,17 @@ public ServiceSASSignatureValues protocol(SASProtocol protocol) { } /** - * When the SAS will take effect. + * @return when the SAS will take effect. */ public OffsetDateTime startTime() { return startTime; } /** - * When the SAS will take effect. + * Sets when the SAS will take effect. + * + * @param startTime When the SAS takes effect + * @return the updated ServiceSASSignatureValues object */ public ServiceSASSignatureValues startTime(OffsetDateTime startTime) { this.startTime = startTime; @@ -153,14 +162,17 @@ public ServiceSASSignatureValues startTime(OffsetDateTime startTime) { } /** - * The time after which the SAS will no longer work. + * @return the time after which the SAS will no longer work. */ public OffsetDateTime expiryTime() { return expiryTime; } /** - * The time after which the SAS will no longer work. + * Sets the time after which the SAS will no longer work. + * + * @param expiryTime When the SAS will no longer work + * @return the updated ServiceSASSignatureValues object */ public ServiceSASSignatureValues expiryTime(OffsetDateTime expiryTime) { this.expiryTime = expiryTime; @@ -168,16 +180,19 @@ public ServiceSASSignatureValues expiryTime(OffsetDateTime expiryTime) { } /** - * Please refer to either {@link ContainerSASPermission} or {@link BlobSASPermission} depending on the resource - * being accessed for help constructing the permissions string. + * @return the permissions string allowed by the SAS. Please refer to either {@link ContainerSASPermission} or + * {@link BlobSASPermission} depending on the resource being accessed for help determining the pernissions allowed. */ public String permissions() { return permissions; } /** - * Please refer to either {@link ContainerSASPermission} or {@link BlobSASPermission} depending on the resource - * being accessed for help constructing the permissions string. + * Sets the permissions string allowed by the SAS. Please refer to either {@link ContainerSASPermission} or + * {@link BlobSASPermission} depending on the resource being accessed for help constructing the permissions string. + * + * @param permissions Permissions string for the SAS + * @return the updated ServiceSASSignatureValues object */ public ServiceSASSignatureValues permissions(String permissions) { this.permissions = permissions; @@ -185,14 +200,17 @@ public ServiceSASSignatureValues permissions(String permissions) { } /** - * {@link IPRange} + * @return the {@link IPRange} which determines the IP ranges that are allowed to use the SAS. */ public IPRange ipRange() { return ipRange; } /** - * {@link IPRange} + * Sets the {@link IPRange} which determines the IP ranges that are allowed to use the SAS. + * + * @param ipRange Allowed IP range to set + * @return the updated ServiceSASSignatureValues object */ public ServiceSASSignatureValues ipRange(IPRange ipRange) { this.ipRange = ipRange; @@ -200,14 +218,17 @@ public ServiceSASSignatureValues ipRange(IPRange ipRange) { } /** - * The resource the SAS user may access. + * @return the resource the SAS user may access. */ public String resource() { return resource; } /** - * The resource the SAS user may access. + * Sets the resource the SAS user may access. + * + * @param resource Allowed resources string to set + * @return the updated ServiceSASSignatureValues object */ public ServiceSASSignatureValues resource(String resource) { this.resource = resource; @@ -215,14 +236,17 @@ public ServiceSASSignatureValues resource(String resource) { } /** - * The canonical name of the object the SAS user may access. + * @return the canonical name of the object the SAS user may access. */ public String canonicalName() { return canonicalName; } /** - * The canonical name of the object the SAS user may access. + * Sets the canonical name of the object the SAS user may access. + * + * @param canonicalName Canonical name of the object the SAS grants access + * @return the updated ServiceSASSignatureValues object */ public ServiceSASSignatureValues canonicalName(String canonicalName) { this.canonicalName = canonicalName; @@ -230,34 +254,38 @@ public ServiceSASSignatureValues canonicalName(String canonicalName) { } /** - * The canonical name of the object the SAS user may access. + * Sets the canonical name of the object the SAS user may access. Constructs a canonical name of + * "/blob/{accountName}{Path of urlString}". * - * @throws RuntimeException If urlString is a malformed URL. + * @param urlString URL string that contains the path to the object + * @param accountName Name of the account that contains the object + * @return the updated ServiceSASSignatureValues object + * @throws RuntimeException If {@code urlString} is a malformed URL. */ public ServiceSASSignatureValues canonicalName(String urlString, String accountName) { - URL url = null; + URL url; 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(); - + this.canonicalName = String.format("/blob/%s%s", accountName, url.getPath()); return this; } /** - * The specific snapshot the SAS user may access. + * @return the specific snapshot the SAS user may access. */ public String snapshotId() { return this.snapshotId; } /** - * The specific snapshot the SAS user may access. + * Sets the specific snapshot the SAS user may access. + * + * @param snapshotId Identifier of the snapshot + * @return the updated ServiceSASSignatureValues object */ public ServiceSASSignatureValues snapshotId(String snapshotId) { this.snapshotId = snapshotId; @@ -265,7 +293,7 @@ public ServiceSASSignatureValues snapshotId(String snapshotId) { } /** - * The name of the access policy on the container this SAS references if any. Please see + * @return the name of the access policy on the container this SAS references if any. Please see * here * for more information. */ @@ -274,9 +302,12 @@ public String identifier() { } /** - * The name of the access policy on the container this SAS references if any. Please see + * Sets the name of the access policy on the container this SAS references if any. Please see * here * for more information. + * + * @param identifier Name of the access policy + * @return the updated ServiceSASSignatureValues object */ public ServiceSASSignatureValues identifier(String identifier) { this.identifier = identifier; @@ -284,14 +315,17 @@ public ServiceSASSignatureValues identifier(String identifier) { } /** - * The cache-control header for the SAS. + * @return the cache-control header for the SAS. */ public String cacheControl() { return cacheControl; } /** - * The cache-control header for the SAS. + * Sets the cache-control header for the SAS. + * + * @param cacheControl Cache-Control header value + * @return the updated ServiceSASSignatureValues object */ public ServiceSASSignatureValues cacheControl(String cacheControl) { this.cacheControl = cacheControl; @@ -299,14 +333,17 @@ public ServiceSASSignatureValues cacheControl(String cacheControl) { } /** - * The content-disposition header for the SAS. + * @return the content-disposition header for the SAS. */ public String contentDisposition() { return contentDisposition; } /** - * The content-disposition header for the SAS. + * Sets the content-disposition header for the SAS. + * + * @param contentDisposition Content-Disposition header value + * @return the updated ServiceSASSignatureValues object */ public ServiceSASSignatureValues contentDisposition(String contentDisposition) { this.contentDisposition = contentDisposition; @@ -314,14 +351,17 @@ public ServiceSASSignatureValues contentDisposition(String contentDisposition) { } /** - * The content-encoding header for the SAS. + * @return the content-encoding header for the SAS. */ public String contentEncoding() { return contentEncoding; } /** - * The content-encoding header for the SAS. + * Sets the content-encoding header for the SAS. + * + * @param contentEncoding Content-Encoding header value + * @return the updated ServiceSASSignatureValues object */ public ServiceSASSignatureValues contentEncoding(String contentEncoding) { this.contentEncoding = contentEncoding; @@ -329,14 +369,17 @@ public ServiceSASSignatureValues contentEncoding(String contentEncoding) { } /** - * The content-language header for the SAS. + * @return the content-language header for the SAS. */ public String contentLanguage() { return contentLanguage; } /** - * The content-language header for the SAS. + * Sets the content-language header for the SAS. + * + * @param contentLanguage Content-Language header value + * @return the updated ServiceSASSignatureValues object */ public ServiceSASSignatureValues contentLanguage(String contentLanguage) { this.contentLanguage = contentLanguage; @@ -344,14 +387,17 @@ public ServiceSASSignatureValues contentLanguage(String contentLanguage) { } /** - * The content-type header for the SAS. + * @return the content-type header for the SAS. */ public String contentType() { return contentType; } /** - * The content-type header for the SAS. + * Sets the content-type header for the SAS. + * + * @param contentType Content-Type header value + * @return the updated ServiceSASSignatureValues object */ public ServiceSASSignatureValues contentType(String contentType) { this.contentType = contentType; @@ -373,7 +419,7 @@ public SASQueryParameters generateSASQueryParameters(SharedKeyCredential sharedK // Signature is generated on the un-url-encoded values. final String stringToSign = stringToSign(); - String signature = null; + String signature; try { signature = sharedKeyCredentials.computeHmac256(stringToSign); } catch (InvalidKeyException e) { @@ -400,7 +446,7 @@ public SASQueryParameters generateSASQueryParameters(UserDelegationKey delegatio // Signature is generated on the un-url-encoded values. final String stringToSign = stringToSign(delegationKey); - String signature = null; + String signature; try { signature = Utility.delegateComputeHmac256(delegationKey, stringToSign); } catch (InvalidKeyException e) { @@ -420,21 +466,17 @@ private void assertGenerateOK(boolean usingUserDelegation) { Utility.assertNotNull("version", this.version); Utility.assertNotNull("canonicalName", this.canonicalName); - // 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 a UserDelegation key or a SignedIdentifier is not being used both expiryDate and permissions must be set. + if (usingUserDelegation || identifier == null) { Utility.assertNotNull("expiryTime", this.expiryTime); Utility.assertNotNull("permissions", this.permissions); + } else if (!usingUserDelegation) { + // Otherwise a SignedIdentifier must be used. + Utility.assertNotNull("identifier", this.identifier); } - 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."); - } + if (Constants.UrlConstants.SAS_CONTAINER_CONSTANT.equals(this.resource) && this.snapshotId != null) { + throw new IllegalArgumentException("Cannot set a snapshotId without resource being a blob."); } } diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/UnexpectedLengthException.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/UnexpectedLengthException.java new file mode 100644 index 0000000000000..3fa8b292768d3 --- /dev/null +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/UnexpectedLengthException.java @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.storage.blob; + +/** + * This exception class represents an error when the specified input length doesn't match the data length. + */ +public final class UnexpectedLengthException extends IllegalStateException { + private final long bytesRead; + private final long bytesExpected; + + UnexpectedLengthException(String message, long bytesRead, long bytesExpected) { + super(message); + this.bytesRead = bytesRead; + this.bytesExpected = bytesExpected; + } + + /** + * @return the number of bytes read from the input + */ + public long bytesRead() { + return this.bytesRead; + } + + /** + * @return the number of bytes that were expected to be read from the input + */ + public long bytesExpected() { + return this.bytesExpected; + } +} diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/BlobHierarchyListSegment.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/BlobHierarchyListSegment.java index d90e89ab602f3..c1885f617481d 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/BlobHierarchyListSegment.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/BlobHierarchyListSegment.java @@ -6,7 +6,9 @@ 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,6 +16,7 @@ * The BlobHierarchyListSegment model. */ @JacksonXmlRootElement(localName = "Blobs") +@JsonDeserialize(using = CustomHierarchicalListingDeserializer.class) @Fluent public final class BlobHierarchyListSegment { /* diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/BlobRange.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/BlobRange.java index 183ebbf5664ad..6dd489b399813 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/BlobRange.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/BlobRange.java @@ -40,11 +40,10 @@ public BlobRange(long offset) { * @param count * the number of bytes to download */ - public BlobRange(long offset, long count) { + public BlobRange(long offset, Long count) { this(offset); - if (count < 0) { - throw new IllegalArgumentException( - "BlobRange count must be greater than or equal to 0 if specified."); + if (count != null || count < 0) { + throw new IllegalArgumentException("BlobRange count must be greater than or equal to 0 if specified."); } this.count = count; } diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/common/policy/RequestRetryOptions.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/common/policy/RequestRetryOptions.java index 80b157bff4716..ae0519ee6a03c 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/common/policy/RequestRetryOptions.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/common/policy/RequestRetryOptions.java @@ -6,9 +6,9 @@ import java.util.concurrent.TimeUnit; /** - * Options for configuring the {@link RequestRetryPolicy}. Please refer to the Factory for more information. Note - * that there is no option for overall operation timeout. This is because Rx object have a timeout field which provides - * this functionality. + * Options for configuring the {@link RequestRetryPolicy}. Please refer to the Factory for more information. Note that + * there is no option for overall operation timeout. This is because Rx object have a timeout field which provides this + * functionality. */ public final class RequestRetryOptions { @@ -16,11 +16,8 @@ public final class RequestRetryOptions { private final int tryTimeout; private final long retryDelayInMs; private final long maxRetryDelayInMs; - /** - * A {@link RetryPolicyType} telling the pipeline what kind of retry policy to use. - */ - private RetryPolicyType retryPolicyType; - private String secondaryHost; + private final RetryPolicyType retryPolicyType; + private final String secondaryHost; /** * Constructor with default retry values: Exponential backoff, maxTries=4, tryTimeout=30, retryDelayInMs=4000, @@ -28,47 +25,43 @@ public final class RequestRetryOptions { */ public RequestRetryOptions() { this(RetryPolicyType.EXPONENTIAL, null, - null, null, null, null); + null, null, null, null); } /** * Configures how the {@link com.azure.core.http.HttpPipeline} should retry requests. * - * @param retryPolicyType - * A {@link RetryPolicyType} specifying the type of retry pattern to use. A value of {@code null} accepts - * the default. - * @param maxTries - * Specifies the maximum number of attempts an operation will be tried before producing an error. A value of - * {@code null} means that you accept our default policy. A value of 1 means 1 try and no retries. - * @param tryTimeout - * Indicates the maximum time allowed for any single try of an HTTP request. A value of {@code null} means - * that you accept our default. NOTE: When transferring large amounts of data, the default TryTimeout will - * probably not be sufficient. You should override this value based on the bandwidth available to the host - * machine and proximity to the Storage service. A good starting point may be something like (60 seconds per - * MB of anticipated-payload-size). - * @param retryDelayInMs - * Specifies the amount of delay to use before retrying an operation. A value of {@code null} means you - * accept the default value. The delay increases (exponentially or linearly) with each retry up to a maximum - * specified by MaxRetryDelay. If you specify {@code null}, then you must also specify {@code null} for - * MaxRetryDelay. - * @param maxRetryDelayInMs - * Specifies the maximum delay allowed before retrying an operation. A value of {@code null} means you - * accept the default value. If you specify {@code null}, then you must also specify {@code null} for - * RetryDelay. - * @param secondaryHost - * If a secondaryHost is specified, retries will be tried against this host. If secondaryHost is - * {@code null} (the default) then operations are not retried against another host. NOTE: Before setting - * this field, make sure you understand the issues around reading stale and potentially-inconsistent data at - * this webpage - * @throws IllegalArgumentException If {@code retryDelayInMs} and {@code maxRetryDelayInMs} are not both null or non-null - * or {@code retryPolicyType} isn't {@link RetryPolicyType#EXPONENTIAL} or {@link RetryPolicyType#FIXED}. + * @param retryPolicyType A {@link RetryPolicyType} specifying the type of retry pattern to use. A value of {@code + * null} accepts the default. + * @param maxTries Specifies the maximum number of attempts an operation will be tried before producing an error. A + * value of {@code null} means that you accept our default policy. A value of 1 means 1 try and no retries. + * @param tryTimeout Indicates the maximum time allowed for any single try of an HTTP request. A value of {@code + * null} means that you accept our default. NOTE: When transferring large amounts of data, the default TryTimeout + * will probably not be sufficient. You should override this value based on the bandwidth available to the host + * machine and proximity to the Storage service. A good starting point may be something like (60 seconds per MB of + * anticipated-payload-size). + * @param retryDelayInMs Specifies the amount of delay to use before retrying an operation. A value of {@code null} + * means you accept the default value. The delay increases (exponentially or linearly) with each retry up to a + * maximum specified by MaxRetryDelay. If you specify {@code null}, then you must also specify {@code null} for + * MaxRetryDelay. + * @param maxRetryDelayInMs Specifies the maximum delay allowed before retrying an operation. A value of {@code + * null} means you accept the default value. If you specify {@code null}, then you must also specify {@code null} + * for RetryDelay. + * @param secondaryHost If a secondaryHost is specified, retries will be tried against this host. If secondaryHost + * is {@code null} (the default) then operations are not retried against another host. NOTE: Before setting this + * field, make sure you understand the issues around reading stale and potentially-inconsistent data at + * this + * webpage + * @throws IllegalArgumentException If {@code retryDelayInMs} and {@code maxRetryDelayInMs} are not both null or + * non-null or {@code retryPolicyType} isn't {@link RetryPolicyType#EXPONENTIAL} or {@link RetryPolicyType#FIXED}. * *Sample Code
* - *For more samples, please see the samples file
+ *For more samples, please see the samples + * file
*/ public RequestRetryOptions(RetryPolicyType retryPolicyType, Integer maxTries, Integer tryTimeout, - Long retryDelayInMs, Long maxRetryDelayInMs, String secondaryHost) { + Long retryDelayInMs, Long maxRetryDelayInMs, String secondaryHost) { this.retryPolicyType = retryPolicyType == null ? RetryPolicyType.EXPONENTIAL : retryPolicyType; if (maxTries != null) { assertInBounds("maxRetries", maxTries, 1, Integer.MAX_VALUE); @@ -85,7 +78,7 @@ public RequestRetryOptions(RetryPolicyType retryPolicyType, Integer maxTries, In } if ((retryDelayInMs == null && maxRetryDelayInMs != null) - || (retryDelayInMs != null && maxRetryDelayInMs == null)) { + || (retryDelayInMs != null && maxRetryDelayInMs == null)) { throw new IllegalArgumentException("Both retryDelay and maxRetryDelay must be null or neither can be null"); } @@ -111,36 +104,49 @@ public RequestRetryOptions(RetryPolicyType retryPolicyType, Integer maxTries, In this.secondaryHost = secondaryHost; } - int maxTries() { + /** + * @return the maximum number attempts that will be retried before the operation finally fails. + */ + public int maxTries() { return this.maxTries; } - int tryTimeout() { + /** + * @return the timeout in seconds allowed for each retry operation. + */ + public int tryTimeout() { return this.tryTimeout; } - String secondaryHost() { + /** + * @return the secondary host that retries could be attempted against. + */ + public String secondaryHost() { return this.secondaryHost; } - long retryDelayInMs() { + /** + * @return the delay in milliseconds between retry attempts. + */ + public long retryDelayInMs() { return retryDelayInMs; } - long maxRetryDelayInMs() { + /** + * @return the maximum delay in milliseconds between retry attempts. + */ + public long maxRetryDelayInMs() { return maxRetryDelayInMs; } /** * Calculates how long to delay before sending the next request. * - * @param tryCount - * An {@code int} indicating which try we are on. - * + * @param tryCount An {@code int} indicating which try we are on. * @return A {@code long} value of how many milliseconds to delay. */ long calculateDelayInMs(int tryCount) { - long delay = 0; + long delay; switch (this.retryPolicyType) { case EXPONENTIAL: delay = (pow(2L, tryCount - 1) - 1L) * this.retryDelayInMs; diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/common/policy/RequestRetryPolicy.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/common/policy/RequestRetryPolicy.java index 774a44999ce76..83bef0b2b49fd 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/common/policy/RequestRetryPolicy.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/common/policy/RequestRetryPolicy.java @@ -22,10 +22,10 @@ import java.util.concurrent.TimeoutException; /** - * This is a request policy in an {@link com.azure.core.http.HttpPipeline} for retrying a given HTTP request. The request - * that is retried will be identical each time it is reissued. Retries will try against a secondary if one is specified - * and the type of operation/error indicates that the secondary can handle the request. Exponential and fixed backoff are - * supported. The policy must only be used directly when creating a custom pipeline. + * This is a request policy in an {@link com.azure.core.http.HttpPipeline} for retrying a given HTTP request. The + * request that is retried will be identical each time it is reissued. Retries will try against a secondary if one is + * specified and the type of operation/error indicates that the secondary can handle the request. Exponential and fixed + * backoff are supported. The policy must only be used directly when creating a custom pipeline. */ public final class RequestRetryPolicy implements HttpPipelinePolicy { private final RequestRetryOptions requestRetryOptions; @@ -41,40 +41,32 @@ public RequestRetryPolicy(RequestRetryOptions requestRetryOptions) { @Override public Mono
- * Exponential retry algorithm: ((2 ^ attempt) - 1) * delay * random(0.8, 1.2) When to retry: connection failure
- * or an HTTP status code of 500 or greater, except 501 and 505 If using a secondary: Odd tries go against
- * primary; even tries go against the secondary For a primary wait ((2 ^ primaryTries - 1) * delay * random(0.8,
- * 1.2) If secondary gets a 404, don't fail, retry but future retries are only against the primary When retrying
- * against a secondary, ignore the retry count and wait (.1 second * random(0.8, 1.2))
+ * Exponential retry algorithm: ((2 ^ attempt) - 1) * delay * random(0.8, 1.2) When to retry: connection failure or
+ * an HTTP status code of 500 or greater, except 501 and 505 If using a secondary: Odd tries go against primary;
+ * even tries go against the secondary For a primary wait ((2 ^ primaryTries - 1) * delay * random(0.8, 1.2) If
+ * secondary gets a 404, don't fail, retry but future retries are only against the primary When retrying against a
+ * secondary, ignore the retry count and wait (.1 second * random(0.8, 1.2))
*
- * @param httpRequest
- * The request to try.
- * @param primaryTry
- * This indicates how man tries we've attempted against the primary DC.
- * @param considerSecondary
- * Before each try, we'll select either the primary or secondary URL if appropriate.
- * @param attempt
- * This indicates the total number of attempts to send the request.
- *
- * @return A single containing either the successful response or an error that was not retryable because either
- * the maxTries was exceeded or retries will not mitigate the issue.
+ * @param context The request to try.
+ * @param next The next policy to apply to the request
+ * @param originalRequest The unmodified original request
+ * @param primaryTry This indicates how man tries we've attempted against the primary DC.
+ * @param attempt This indicates the total number of attempts to send the request.
+ * @return A single containing either the successful response or an error that was not retryable because either the
+ * maxTries was exceeded or retries will not mitigate the issue.
*/
- private Mono