diff --git a/eng/versioning/external_dependencies.txt b/eng/versioning/external_dependencies.txt index d23f3b1c80d3..b87325d7f361 100644 --- a/eng/versioning/external_dependencies.txt +++ b/eng/versioning/external_dependencies.txt @@ -162,6 +162,10 @@ commons-io:commons-io;2.17.0 net.java.dev.jna:jna-platform;5.17.0 net.oneandone.reflections8:reflections8;0.11.7 net.jonathangiles.tools:dependencyChecker-maven-plugin;1.0.6 +org.apache.arrow:arrow-format;18.1.0 +org.apache.arrow:arrow-memory-core;18.1.0 +org.apache.arrow:arrow-memory-unsafe;18.1.0 +org.apache.arrow:arrow-vector;18.1.0 org.apache.commons:commons-collections4;4.4 org.apache.commons:commons-text;1.10.0 org.apache.maven:maven-plugin-api;3.9.11 @@ -186,6 +190,7 @@ org.apache.maven.plugins:maven-shade-plugin;3.6.0 org.apache.maven.plugins:maven-site-plugin;3.21.0 org.apache.maven.plugins:maven-source-plugin;3.3.1 org.apache.maven.plugins:maven-surefire-plugin;3.5.3 +org.checkerframework:checker-qual;3.42.0 org.codehaus.mojo:animal-sniffer-maven-plugin;1.24 org.codehaus.mojo:build-helper-maven-plugin;3.6.1 org.codehaus.mojo:exec-maven-plugin;3.5.1 diff --git a/sdk/parents/azure-client-sdk-parent/pom.xml b/sdk/parents/azure-client-sdk-parent/pom.xml index 7e329e6b1002..9e7a897b26a9 100644 --- a/sdk/parents/azure-client-sdk-parent/pom.xml +++ b/sdk/parents/azure-client-sdk-parent/pom.xml @@ -602,6 +602,11 @@ com.google.code.findbugs:jsr305:[3.0.2] + + org.apache.arrow:arrow-memory-core:[18.1.0] + org.apache.arrow:arrow-memory-unsafe:[18.1.0] + org.apache.arrow:arrow-vector:[18.1.0] + org.checkerframework:checker-qual:[3.42.0] diff --git a/sdk/storage/azure-storage-blob/assets.json b/sdk/storage/azure-storage-blob/assets.json index 7f5e5b611d0c..343f43c946b6 100644 --- a/sdk/storage/azure-storage-blob/assets.json +++ b/sdk/storage/azure-storage-blob/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "java", "TagPrefix": "java/storage/azure-storage-blob", - "Tag": "java/storage/azure-storage-blob_1da9542ee2" + "Tag": "java/storage/azure-storage-blob_65730d9920" } diff --git a/sdk/storage/azure-storage-blob/pom.xml b/sdk/storage/azure-storage-blob/pom.xml index 0971e45577a2..5e4d33329fc1 100644 --- a/sdk/storage/azure-storage-blob/pom.xml +++ b/sdk/storage/azure-storage-blob/pom.xml @@ -56,6 +56,8 @@ --add-reads com.azure.storage.blob=com.azure.core.http.okhttp --add-reads com.azure.storage.blob=com.azure.core.http.jdk.httpclient --add-reads com.azure.storage.blob=com.azure.core.http.vertx + --add-opens java.base/java.nio=ALL-UNNAMED + --add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED concurrent @@ -138,6 +140,29 @@ 1.17.7 test + + + + org.apache.arrow + arrow-vector + 18.1.0 + + + org.apache.arrow + arrow-memory-core + 18.1.0 + + + org.apache.arrow + arrow-memory-unsafe + 18.1.0 + + + org.checkerframework + checker-qual + 3.42.0 + + diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobContainerAsyncClient.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobContainerAsyncClient.java index b86fe4e76b2f..c35a9ff13ab5 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobContainerAsyncClient.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobContainerAsyncClient.java @@ -28,6 +28,7 @@ import com.azure.storage.blob.implementation.models.EncryptionScope; import com.azure.storage.blob.implementation.models.ListBlobsFlatSegmentResponse; import com.azure.storage.blob.implementation.models.ListBlobsHierarchySegmentResponse; +import com.azure.storage.blob.implementation.util.ArrowBlobListDeserializer; import com.azure.storage.blob.implementation.util.BlobConstants; import com.azure.storage.blob.implementation.util.BlobSasImplUtil; import com.azure.storage.blob.implementation.util.ModelHelper; @@ -42,6 +43,7 @@ import com.azure.storage.blob.models.CustomerProvidedKey; import com.azure.storage.blob.models.ListBlobsIncludeItem; import com.azure.storage.blob.models.ListBlobsOptions; +import com.azure.storage.blob.models.StorageResponseSerializationFormat; import com.azure.storage.blob.models.PublicAccessType; import com.azure.storage.blob.models.StorageAccountInfo; import com.azure.storage.blob.models.TaggedBlobItem; @@ -1125,11 +1127,22 @@ PagedFlux listBlobsFlatWithOptionalTimeout(ListBlobsOptions options, S finalOptions = new ListBlobsOptions().setMaxResultsPerPage(pageSize) .setPrefix(options.getPrefix()) .setDetails(options.getDetails()); + if (ModelHelper.resolveSerializationFormat(options.getStorageResponseSerializationFormat()) + == StorageResponseSerializationFormat.ARROW) { + finalOptions.setStorageResponseSerializationFormat(StorageResponseSerializationFormat.ARROW) + .setEndBefore(options.getEndBefore()); + } } } else { finalOptions = options; } + if (finalOptions != null + && ModelHelper.resolveSerializationFormat(finalOptions.getStorageResponseSerializationFormat()) + == StorageResponseSerializationFormat.ARROW) { + return listBlobsFlatSegmentArrow(marker, finalOptions, timeout); + } + return listBlobsFlatSegment(marker, finalOptions, timeout).map(response -> { List value = response.getValue().getSegment() == null ? Collections.emptyList() @@ -1177,6 +1190,62 @@ PagedFlux listBlobsFlatWithOptionalTimeout(ListBlobsOptions options, S timeout); } + private Mono> listBlobsFlatSegmentArrow(String marker, ListBlobsOptions options, + Duration timeout) { + options = options == null ? new ListBlobsOptions() : options; + + ArrayList include + = options.getDetails().toList().isEmpty() ? null : options.getDetails().toList(); + + ListBlobsOptions finalOptions = options; + return StorageImplUtils.applyOptionalTimeout(this.azureBlobStorage.getContainers() + .listBlobFlatSegmentApacheArrowWithResponseAsync(containerName, finalOptions.getPrefix(), marker, + finalOptions.getMaxResultsPerPage(), include, null, finalOptions.getStartFrom(), + finalOptions.getEndBefore(), null, Context.NONE), + timeout).flatMap(response -> { + String contentType = response.getHeaders().getValue(com.azure.core.http.HttpHeaderName.CONTENT_TYPE); + + return FluxUtil.collectBytesInByteBufferStream(response.getValue()).map(bytes -> { + java.io.ByteArrayInputStream bais = new java.io.ByteArrayInputStream(bytes); + + if (contentType != null && contentType.contentEquals("application/vnd.apache.arrow.stream")) { + ArrowBlobListDeserializer.ArrowListBlobsResult arrowResult + = ArrowBlobListDeserializer.deserialize(bais); + + List value = arrowResult.getBlobItems() + .stream() + .map(ModelHelper::populateBlobItem) + .collect(Collectors.toList()); + + return (PagedResponse) new PagedResponseBase<>(response.getRequest(), + response.getStatusCode(), response.getHeaders(), value, arrowResult.getNextMarker(), + response.getDeserializedHeaders()); + } else { + // XML fallback + try { + ListBlobsFlatSegmentResponse xmlResponse + = ListBlobsFlatSegmentResponse.fromXml(com.azure.xml.XmlReader.fromStream(bais)); + + List value = xmlResponse.getSegment() == null + ? Collections.emptyList() + : xmlResponse.getSegment() + .getBlobItems() + .stream() + .map(ModelHelper::populateBlobItem) + .collect(Collectors.toList()); + + return (PagedResponse) new PagedResponseBase<>(response.getRequest(), + response.getStatusCode(), response.getHeaders(), value, xmlResponse.getNextMarker(), + null); + } catch (javax.xml.stream.XMLStreamException e) { + throw LOGGER + .logExceptionAsError(new RuntimeException("Failed to parse XML fallback response", e)); + } + } + }); + }); + } + /** * 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. @@ -1302,10 +1371,22 @@ PagedFlux listBlobsHierarchyWithOptionalTimeout(String delimiter, List .setPrefix(options.getPrefix()) .setDetails(options.getDetails()) .setStartFrom(options.getStartFrom()); + if (ModelHelper.resolveSerializationFormat(options.getStorageResponseSerializationFormat()) + == StorageResponseSerializationFormat.ARROW) { + finalOptions.setStorageResponseSerializationFormat(StorageResponseSerializationFormat.ARROW) + .setEndBefore(options.getEndBefore()); + } } } else { finalOptions = options; } + + if (finalOptions != null + && ModelHelper.resolveSerializationFormat(finalOptions.getStorageResponseSerializationFormat()) + == StorageResponseSerializationFormat.ARROW) { + return listBlobsHierarchySegmentArrow(marker, delimiter, finalOptions, timeout); + } + return listBlobsHierarchySegment(marker, delimiter, finalOptions, timeout).map(response -> { BlobHierarchyListSegment segment = response.getValue().getSegment(); List value; @@ -1344,6 +1425,71 @@ PagedFlux listBlobsHierarchyWithOptionalTimeout(String delimiter, List timeout); } + private Mono> listBlobsHierarchySegmentArrow(String marker, String delimiter, + ListBlobsOptions options, Duration timeout) { + options = options == null ? new ListBlobsOptions() : options; + if (options.getDetails().getRetrieveSnapshots()) { + throw LOGGER.logExceptionAsError( + new UnsupportedOperationException("Including snapshots in a hierarchical listing is not supported.")); + } + + ArrayList include + = options.getDetails().toList().isEmpty() ? null : options.getDetails().toList(); + + ListBlobsOptions finalOptions = options; + return StorageImplUtils + .applyOptionalTimeout(this.azureBlobStorage.getContainers() + .listBlobHierarchySegmentApacheArrowWithResponseAsync(containerName, delimiter, + finalOptions.getPrefix(), marker, finalOptions.getMaxResultsPerPage(), include, null, + finalOptions.getStartFrom(), finalOptions.getEndBefore(), null, Context.NONE), + timeout) + .flatMap(response -> { + String contentType = response.getHeaders().getValue(com.azure.core.http.HttpHeaderName.CONTENT_TYPE); + + return FluxUtil.collectBytesInByteBufferStream(response.getValue()).map(bytes -> { + java.io.ByteArrayInputStream bais = new java.io.ByteArrayInputStream(bytes); + + if (contentType != null && contentType.contentEquals("application/vnd.apache.arrow.stream")) { + ArrowBlobListDeserializer.ArrowListBlobsResult arrowResult + = ArrowBlobListDeserializer.deserialize(bais); + + List value = arrowResult.getBlobItems() + .stream() + .map(ModelHelper::populateBlobItem) + .collect(Collectors.toList()); + + return (PagedResponse) new PagedResponseBase<>(response.getRequest(), + response.getStatusCode(), response.getHeaders(), value, arrowResult.getNextMarker(), + response.getDeserializedHeaders()); + } else { + // XML fallback + try { + ListBlobsHierarchySegmentResponse xmlResponse + = ListBlobsHierarchySegmentResponse.fromXml(com.azure.xml.XmlReader.fromStream(bais)); + + BlobHierarchyListSegment segment = xmlResponse.getSegment(); + List value = new ArrayList<>(); + if (segment != null) { + segment.getBlobItems() + .forEach(item -> value.add(BlobItemConstructorProxy.create(item))); + segment.getBlobPrefixes() + .forEach(prefix -> value + .add(new BlobItem().setName(ModelHelper.toBlobNameString(prefix.getName())) + .setIsPrefix(true))); + } + + return (PagedResponse) new PagedResponseBase<>(response.getRequest(), + response.getStatusCode(), response.getHeaders(), value, xmlResponse.getNextMarker(), + null); + } catch (javax.xml.stream.XMLStreamException e) { + throw LOGGER + .logExceptionAsError(new RuntimeException("Failed to parse XML fallback response", e)); + } + } + }); + }); + } + /** * Returns a reactive Publisher emitting the blobs in this container whose tags match the query expression. For more * information, including information on the query syntax, see the Azure Docs. diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobContainerClient.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobContainerClient.java index 64de81617f9c..104f7852b5c7 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobContainerClient.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobContainerClient.java @@ -25,12 +25,15 @@ import com.azure.storage.blob.implementation.models.ContainersGetAccessPolicyHeaders; import com.azure.storage.blob.implementation.models.ContainersGetAccountInfoHeaders; import com.azure.storage.blob.implementation.models.ContainersGetPropertiesHeaders; +import com.azure.storage.blob.implementation.models.ContainersListBlobFlatSegmentApacheArrowHeaders; import com.azure.storage.blob.implementation.models.ContainersListBlobFlatSegmentHeaders; +import com.azure.storage.blob.implementation.models.ContainersListBlobHierarchySegmentApacheArrowHeaders; import com.azure.storage.blob.implementation.models.ContainersListBlobHierarchySegmentHeaders; import com.azure.storage.blob.implementation.models.EncryptionScope; import com.azure.storage.blob.implementation.models.FilterBlobSegment; import com.azure.storage.blob.implementation.models.ListBlobsFlatSegmentResponse; import com.azure.storage.blob.implementation.models.ListBlobsHierarchySegmentResponse; +import com.azure.storage.blob.implementation.util.ArrowBlobListDeserializer; import com.azure.storage.blob.implementation.util.BlobConstants; import com.azure.storage.blob.implementation.util.BlobSasImplUtil; import com.azure.storage.blob.implementation.util.ModelHelper; @@ -47,6 +50,7 @@ import com.azure.storage.blob.models.ListBlobsOptions; import com.azure.storage.blob.models.PublicAccessType; import com.azure.storage.blob.models.StorageAccountInfo; +import com.azure.storage.blob.models.StorageResponseSerializationFormat; import com.azure.storage.blob.models.TaggedBlobItem; import com.azure.storage.blob.models.UserDelegationKey; import com.azure.storage.blob.options.BlobContainerCreateOptions; @@ -57,6 +61,10 @@ import com.azure.storage.common.implementation.SasImplUtils; import com.azure.storage.common.implementation.StorageImplUtils; +import com.azure.xml.XmlReader; + +import java.io.InputStream; +import javax.xml.stream.XMLStreamException; import java.net.URI; import java.time.Duration; import java.time.OffsetDateTime; @@ -1029,6 +1037,10 @@ public PagedIterable listBlobs(ListBlobsOptions options, String contin .setStartFrom(options.getStartFrom()) .setDetails(options.getDetails()); + if (options.getStorageResponseSerializationFormat() == StorageResponseSerializationFormat.ARROW) { + finalOptions.setStorageResponseSerializationFormat(StorageResponseSerializationFormat.ARROW); + } + } /* If pageSize was not set in a .byPage(int) method, the page size from options will be preserved. @@ -1040,26 +1052,71 @@ public PagedIterable listBlobs(ListBlobsOptions options, String contin ArrayList include = finalOptions.getDetails().toList().isEmpty() ? null : finalOptions.getDetails().toList(); - Callable> operation - = () -> this.azureBlobStorage.getContainers() - .listBlobFlatSegmentWithResponse(containerName, finalOptions.getPrefix(), nextMarker, - finalOptions.getMaxResultsPerPage(), include, finalOptions.getStartFrom(), null, null, - Context.NONE); - - ResponseBase response - = StorageImplUtils.sendRequest(operation, timeout, BlobStorageException.class); - - List value = response.getValue().getSegment() == null - ? Collections.emptyList() - : response.getValue() - .getSegment() - .getBlobItems() - .stream() - .map(ModelHelper::populateBlobItem) - .collect(Collectors.toList()); - - return new PagedResponseBase<>(response.getRequest(), response.getStatusCode(), response.getHeaders(), - value, response.getValue().getNextMarker(), response.getDeserializedHeaders()); + if (finalOptions.getStorageResponseSerializationFormat() == StorageResponseSerializationFormat.ARROW) { + Callable> operation + = () -> this.azureBlobStorage.getContainers() + .listBlobFlatSegmentApacheArrowWithResponse(containerName, finalOptions.getPrefix(), nextMarker, + finalOptions.getMaxResultsPerPage(), include, null, finalOptions.getStartFrom(), + finalOptions.getEndBefore(), null, Context.NONE); + ResponseBase response + = StorageImplUtils.sendRequest(operation, timeout, BlobStorageException.class); + + String contentType = response.getHeaders().getValue(com.azure.core.http.HttpHeaderName.CONTENT_TYPE); + + if (contentType != null && contentType.contentEquals("application/vnd.apache.arrow.stream")) { + // Arrow response — parse with Arrow deserializer + ArrowBlobListDeserializer.ArrowListBlobsResult arrowResult + = ArrowBlobListDeserializer.deserialize(response.getValue()); + + List value = arrowResult.getBlobItems() + .stream() + .map(ModelHelper::populateBlobItem) + .collect(Collectors.toList()); + + return new PagedResponseBase<>(response.getRequest(), response.getStatusCode(), + response.getHeaders(), value, arrowResult.getNextMarker(), response.getDeserializedHeaders()); + } else { + // XML fallback — service returned XML instead of Arrow + try { + ListBlobsFlatSegmentResponse xmlResponse + = ListBlobsFlatSegmentResponse.fromXml(XmlReader.fromStream(response.getValue())); + + List value = xmlResponse.getSegment() == null + ? Collections.emptyList() + : xmlResponse.getSegment() + .getBlobItems() + .stream() + .map(ModelHelper::populateBlobItem) + .collect(Collectors.toList()); + + return new PagedResponseBase<>(response.getRequest(), response.getStatusCode(), + response.getHeaders(), value, xmlResponse.getNextMarker(), null); + } catch (XMLStreamException e) { + throw LOGGER + .logExceptionAsError(new RuntimeException("Failed to parse XML fallback response", e)); + } + } + } else { + Callable> operation + = () -> this.azureBlobStorage.getContainers() + .listBlobFlatSegmentWithResponse(containerName, finalOptions.getPrefix(), nextMarker, + finalOptions.getMaxResultsPerPage(), include, finalOptions.getStartFrom(), null, null, + Context.NONE); + ResponseBase response + = StorageImplUtils.sendRequest(operation, timeout, BlobStorageException.class); + + List value = response.getValue().getSegment() == null + ? Collections.emptyList() + : response.getValue() + .getSegment() + .getBlobItems() + .stream() + .map(ModelHelper::populateBlobItem) + .collect(Collectors.toList()); + + return new PagedResponseBase<>(response.getRequest(), response.getStatusCode(), response.getHeaders(), + value, response.getValue().getNextMarker(), response.getDeserializedHeaders()); + } }; return new PagedIterable<>(pageSize -> retriever.apply(continuationToken, pageSize), retriever); @@ -1164,6 +1221,11 @@ public PagedIterable listBlobsByHierarchy(String delimiter, ListBlobsO .setPrefix(options.getPrefix()) .setDetails(options.getDetails()) .setStartFrom(options.getStartFrom()); + if (ModelHelper.resolveSerializationFormat(options.getStorageResponseSerializationFormat()) + == StorageResponseSerializationFormat.ARROW) { + finalOptions.setStorageResponseSerializationFormat(StorageResponseSerializationFormat.ARROW) + .setEndBefore(options.getEndBefore()); + } } /* If pageSize was not set in a .byPage(int) method, the page size from options will be preserved. @@ -1186,25 +1248,72 @@ private PagedResponse listBlobsHierarchySegment(String marker, String ArrayList include = options.getDetails().toList().isEmpty() ? null : options.getDetails().toList(); - Callable> operation - = () -> azureBlobStorage.getContainers() - .listBlobHierarchySegmentWithResponse(containerName, delimiter, options.getPrefix(), marker, - options.getMaxResultsPerPage(), include, options.getStartFrom(), null, null, Context.NONE); + if (ModelHelper.resolveSerializationFormat(options.getStorageResponseSerializationFormat()) + == StorageResponseSerializationFormat.ARROW) { + Callable> operation + = () -> azureBlobStorage.getContainers() + .listBlobHierarchySegmentApacheArrowWithResponse(containerName, delimiter, options.getPrefix(), + marker, options.getMaxResultsPerPage(), include, null, options.getStartFrom(), + options.getEndBefore(), null, Context.NONE); + ResponseBase response + = StorageImplUtils.sendRequest(operation, timeout, BlobStorageException.class); - ResponseBase response - = StorageImplUtils.sendRequest(operation, timeout, BlobStorageException.class); + String contentType = response.getHeaders().getValue(com.azure.core.http.HttpHeaderName.CONTENT_TYPE); - BlobHierarchyListSegment segment = response.getValue().getSegment(); - List value = new ArrayList<>(); - if (segment != null) { - segment.getBlobItems().forEach(item -> value.add(BlobItemConstructorProxy.create(item))); - segment.getBlobPrefixes() - .forEach(prefix -> value - .add(new BlobItem().setName(ModelHelper.toBlobNameString(prefix.getName())).setIsPrefix(true))); - } + if (contentType != null && contentType.contentEquals("application/vnd.apache.arrow.stream")) { + ArrowBlobListDeserializer.ArrowListBlobsResult arrowResult + = ArrowBlobListDeserializer.deserialize(response.getValue()); - return new PagedResponseBase<>(response.getRequest(), response.getStatusCode(), response.getHeaders(), value, - response.getValue().getNextMarker(), response.getDeserializedHeaders()); + List value = arrowResult.getBlobItems() + .stream() + .map(ModelHelper::populateBlobItem) + .collect(Collectors.toList()); + + return new PagedResponseBase<>(response.getRequest(), response.getStatusCode(), response.getHeaders(), + value, arrowResult.getNextMarker(), response.getDeserializedHeaders()); + } else { + // XML fallback — service returned XML instead of Arrow + try { + ListBlobsHierarchySegmentResponse xmlResponse + = ListBlobsHierarchySegmentResponse.fromXml(XmlReader.fromStream(response.getValue())); + + BlobHierarchyListSegment segment = xmlResponse.getSegment(); + List value = new ArrayList<>(); + if (segment != null) { + segment.getBlobItems().forEach(item -> value.add(BlobItemConstructorProxy.create(item))); + segment.getBlobPrefixes() + .forEach(prefix -> value + .add(new BlobItem().setName(ModelHelper.toBlobNameString(prefix.getName())) + .setIsPrefix(true))); + } + + return new PagedResponseBase<>(response.getRequest(), response.getStatusCode(), + response.getHeaders(), value, xmlResponse.getNextMarker(), null); + } catch (XMLStreamException e) { + throw LOGGER.logExceptionAsError(new RuntimeException("Failed to parse XML fallback response", e)); + } + } + } else { + Callable> operation + = () -> azureBlobStorage.getContainers() + .listBlobHierarchySegmentWithResponse(containerName, delimiter, options.getPrefix(), marker, + options.getMaxResultsPerPage(), include, options.getStartFrom(), null, null, Context.NONE); + + ResponseBase response + = StorageImplUtils.sendRequest(operation, timeout, BlobStorageException.class); + + BlobHierarchyListSegment segment = response.getValue().getSegment(); + List value = new ArrayList<>(); + if (segment != null) { + segment.getBlobItems().forEach(item -> value.add(BlobItemConstructorProxy.create(item))); + segment.getBlobPrefixes() + .forEach(prefix -> value + .add(new BlobItem().setName(ModelHelper.toBlobNameString(prefix.getName())).setIsPrefix(true))); + } + + return new PagedResponseBase<>(response.getRequest(), response.getStatusCode(), response.getHeaders(), + value, response.getValue().getNextMarker(), response.getDeserializedHeaders()); + } } /** diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/ContainersImpl.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/ContainersImpl.java index 7fd2af96e4df..6bfa32ac060d 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/ContainersImpl.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/ContainersImpl.java @@ -37,7 +37,9 @@ import com.azure.storage.blob.implementation.models.ContainersGetAccessPolicyHeaders; import com.azure.storage.blob.implementation.models.ContainersGetAccountInfoHeaders; import com.azure.storage.blob.implementation.models.ContainersGetPropertiesHeaders; +import com.azure.storage.blob.implementation.models.ContainersListBlobFlatSegmentApacheArrowHeaders; import com.azure.storage.blob.implementation.models.ContainersListBlobFlatSegmentHeaders; +import com.azure.storage.blob.implementation.models.ContainersListBlobHierarchySegmentApacheArrowHeaders; import com.azure.storage.blob.implementation.models.ContainersListBlobHierarchySegmentHeaders; import com.azure.storage.blob.implementation.models.ContainersReleaseLeaseHeaders; import com.azure.storage.blob.implementation.models.ContainersRenameHeaders; @@ -853,6 +855,56 @@ Response listBlobFlatSegmentNoCustomHeadersSync(@H @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @HeaderParam("Accept") String accept, Context context); + @Get("/{containerName}") + @ExpectedResponses({ 200 }) + @UnexpectedResponseExceptionType(BlobStorageExceptionInternal.class) + Mono>> + listBlobFlatSegmentApacheArrow(@HostParam("url") String url, + @PathParam("containerName") String containerName, @QueryParam("restype") String restype, + @QueryParam("comp") String comp, @HeaderParam("Accept") String accept, + @QueryParam("prefix") String prefix, @QueryParam("marker") String marker, + @QueryParam("maxresults") Integer maxresults, @QueryParam("include") String include, + @QueryParam("timeout") Integer timeout, @QueryParam("startFrom") String startFrom, + @QueryParam("endBefore") String endBefore, @HeaderParam("x-ms-version") String version, + @HeaderParam("x-ms-client-request-id") String requestId, Context context); + + @Get("/{containerName}") + @ExpectedResponses({ 200 }) + @UnexpectedResponseExceptionType(BlobStorageExceptionInternal.class) + Mono listBlobFlatSegmentApacheArrowNoCustomHeaders(@HostParam("url") String url, + @PathParam("containerName") String containerName, @QueryParam("restype") String restype, + @QueryParam("comp") String comp, @HeaderParam("Accept") String accept, @QueryParam("prefix") String prefix, + @QueryParam("marker") String marker, @QueryParam("maxresults") Integer maxresults, + @QueryParam("include") String include, @QueryParam("timeout") Integer timeout, + @QueryParam("startFrom") String startFrom, @QueryParam("endBefore") String endBefore, + @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, + Context context); + + @Get("/{containerName}") + @ExpectedResponses({ 200 }) + @UnexpectedResponseExceptionType(BlobStorageExceptionInternal.class) + ResponseBase listBlobFlatSegmentApacheArrowSync( + @HostParam("url") String url, @PathParam("containerName") String containerName, + @QueryParam("restype") String restype, @QueryParam("comp") String comp, + @HeaderParam("Accept") String accept, @QueryParam("prefix") String prefix, + @QueryParam("marker") String marker, @QueryParam("maxresults") Integer maxresults, + @QueryParam("include") String include, @QueryParam("timeout") Integer timeout, + @QueryParam("startFrom") String startFrom, @QueryParam("endBefore") String endBefore, + @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, + Context context); + + @Get("/{containerName}") + @ExpectedResponses({ 200 }) + @UnexpectedResponseExceptionType(BlobStorageExceptionInternal.class) + Response listBlobFlatSegmentApacheArrowNoCustomHeadersSync(@HostParam("url") String url, + @PathParam("containerName") String containerName, @QueryParam("restype") String restype, + @QueryParam("comp") String comp, @HeaderParam("Accept") String accept, @QueryParam("prefix") String prefix, + @QueryParam("marker") String marker, @QueryParam("maxresults") Integer maxresults, + @QueryParam("include") String include, @QueryParam("timeout") Integer timeout, + @QueryParam("startFrom") String startFrom, @QueryParam("endBefore") String endBefore, + @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, + Context context); + @Get("/{containerName}") @ExpectedResponses({ 200 }) @UnexpectedResponseExceptionType(BlobStorageExceptionInternal.class) @@ -903,6 +955,58 @@ Response listBlobHierarchySegmentNoCustomHead @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @HeaderParam("Accept") String accept, Context context); + @Get("/{containerName}") + @ExpectedResponses({ 200 }) + @UnexpectedResponseExceptionType(BlobStorageExceptionInternal.class) + Mono>> + listBlobHierarchySegmentApacheArrow(@HostParam("url") String url, + @PathParam("containerName") String containerName, @QueryParam("restype") String restype, + @QueryParam("comp") String comp, @HeaderParam("Accept") String accept, + @QueryParam("prefix") String prefix, @QueryParam("delimiter") String delimiter, + @QueryParam("marker") String marker, @QueryParam("maxresults") Integer maxresults, + @QueryParam("include") String include, @QueryParam("timeout") Integer timeout, + @QueryParam("startFrom") String startFrom, @QueryParam("endBefore") String endBefore, + @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, + Context context); + + @Get("/{containerName}") + @ExpectedResponses({ 200 }) + @UnexpectedResponseExceptionType(BlobStorageExceptionInternal.class) + Mono listBlobHierarchySegmentApacheArrowNoCustomHeaders(@HostParam("url") String url, + @PathParam("containerName") String containerName, @QueryParam("restype") String restype, + @QueryParam("comp") String comp, @HeaderParam("Accept") String accept, @QueryParam("prefix") String prefix, + @QueryParam("delimiter") String delimiter, @QueryParam("marker") String marker, + @QueryParam("maxresults") Integer maxresults, @QueryParam("include") String include, + @QueryParam("timeout") Integer timeout, @QueryParam("startFrom") String startFrom, + @QueryParam("endBefore") String endBefore, @HeaderParam("x-ms-version") String version, + @HeaderParam("x-ms-client-request-id") String requestId, Context context); + + @Get("/{containerName}") + @ExpectedResponses({ 200 }) + @UnexpectedResponseExceptionType(BlobStorageExceptionInternal.class) + ResponseBase + listBlobHierarchySegmentApacheArrowSync(@HostParam("url") String url, + @PathParam("containerName") String containerName, @QueryParam("restype") String restype, + @QueryParam("comp") String comp, @HeaderParam("Accept") String accept, + @QueryParam("prefix") String prefix, @QueryParam("delimiter") String delimiter, + @QueryParam("marker") String marker, @QueryParam("maxresults") Integer maxresults, + @QueryParam("include") String include, @QueryParam("timeout") Integer timeout, + @QueryParam("startFrom") String startFrom, @QueryParam("endBefore") String endBefore, + @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, + Context context); + + @Get("/{containerName}") + @ExpectedResponses({ 200 }) + @UnexpectedResponseExceptionType(BlobStorageExceptionInternal.class) + Response listBlobHierarchySegmentApacheArrowNoCustomHeadersSync(@HostParam("url") String url, + @PathParam("containerName") String containerName, @QueryParam("restype") String restype, + @QueryParam("comp") String comp, @HeaderParam("Accept") String accept, @QueryParam("prefix") String prefix, + @QueryParam("delimiter") String delimiter, @QueryParam("marker") String marker, + @QueryParam("maxresults") Integer maxresults, @QueryParam("include") String include, + @QueryParam("timeout") Integer timeout, @QueryParam("startFrom") String startFrom, + @QueryParam("endBefore") String endBefore, @HeaderParam("x-ms-version") String version, + @HeaderParam("x-ms-client-request-id") String requestId, Context context); + @Get("/{containerName}") @ExpectedResponses({ 200 }) @UnexpectedResponseExceptionType(BlobStorageExceptionInternal.class) @@ -6073,12 +6177,10 @@ public Response listBlobFlatSegmentNoCustomHeaders } /** - * [Update] The List Blobs operation returns a list of the blobs under the specified container. + * The List Blobs operation returns a list of the blobs under the specified container. This operation is for Apache + * Arrow use case so response is returned as raw to be deserialized by the client. * * @param containerName The container name. - * @param delimiter 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. * @param prefix Filters the results to return only containers whose name begins with the specified prefix. * @param marker 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 @@ -6091,36 +6193,35 @@ public Response listBlobFlatSegmentNoCustomHeaders * 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. * @param include Include this parameter to specify one or more datasets to include in the response. - * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is - * supported; For recursive list, multiple entity levels are supported. (Inclusive). * @param timeout The timeout parameter is expressed in seconds. For more information, see <a * href="https://learn.microsoft.com/rest/api/storageservices/setting-timeouts-for-blob-service-operations">Setting * Timeouts for Blob Service Operations.</a>. + * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is + * supported; For recursive list, multiple entity levels are supported. (Inclusive). + * @param endBefore Specifies the relative path to end before list paths. (Exclusive). * @param requestId 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. * @throws IllegalArgumentException thrown if parameters fail the validation. * @throws BlobStorageExceptionInternal thrown if the request is rejected by server. * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. - * @return an enumeration of blobs along with {@link ResponseBase} on successful completion of {@link Mono}. + * @return the response body along with {@link ResponseBase} on successful completion of {@link Mono}. */ @ServiceMethod(returns = ReturnType.SINGLE) - public Mono> - listBlobHierarchySegmentWithResponseAsync(String containerName, String delimiter, String prefix, String marker, - Integer maxresults, List include, String startFrom, Integer timeout, + public Mono>> + listBlobFlatSegmentApacheArrowWithResponseAsync(String containerName, String prefix, String marker, + Integer maxresults, List include, Integer timeout, String startFrom, String endBefore, String requestId) { return FluxUtil - .withContext(context -> listBlobHierarchySegmentWithResponseAsync(containerName, delimiter, prefix, marker, - maxresults, include, startFrom, timeout, requestId, context)) + .withContext(context -> listBlobFlatSegmentApacheArrowWithResponseAsync(containerName, prefix, marker, + maxresults, include, timeout, startFrom, endBefore, requestId, context)) .onErrorMap(BlobStorageExceptionInternal.class, ModelHelper::mapToBlobStorageException); } /** - * [Update] The List Blobs operation returns a list of the blobs under the specified container. + * The List Blobs operation returns a list of the blobs under the specified container. This operation is for Apache + * Arrow use case so response is returned as raw to be deserialized by the client. * * @param containerName The container name. - * @param delimiter 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. * @param prefix Filters the results to return only containers whose name begins with the specified prefix. * @param marker 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 @@ -6133,45 +6234,45 @@ public Response listBlobFlatSegmentNoCustomHeaders * 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. * @param include Include this parameter to specify one or more datasets to include in the response. - * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is - * supported; For recursive list, multiple entity levels are supported. (Inclusive). * @param timeout The timeout parameter is expressed in seconds. For more information, see <a * href="https://learn.microsoft.com/rest/api/storageservices/setting-timeouts-for-blob-service-operations">Setting * Timeouts for Blob Service Operations.</a>. + * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is + * supported; For recursive list, multiple entity levels are supported. (Inclusive). + * @param endBefore Specifies the relative path to end before list paths. (Exclusive). * @param requestId 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. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @throws BlobStorageExceptionInternal thrown if the request is rejected by server. * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. - * @return an enumeration of blobs along with {@link ResponseBase} on successful completion of {@link Mono}. + * @return the response body along with {@link ResponseBase} on successful completion of {@link Mono}. */ @ServiceMethod(returns = ReturnType.SINGLE) - public Mono> - listBlobHierarchySegmentWithResponseAsync(String containerName, String delimiter, String prefix, String marker, - Integer maxresults, List include, String startFrom, Integer timeout, String requestId, - Context context) { + public Mono>> + listBlobFlatSegmentApacheArrowWithResponseAsync(String containerName, String prefix, String marker, + Integer maxresults, List include, Integer timeout, String startFrom, String endBefore, + String requestId, Context context) { final String restype = "container"; final String comp = "list"; - final String accept = "application/xml"; + final String accept = "application/vnd.apache.arrow.stream"; String includeConverted = (include == null) ? null : include.stream() .map(paramItemValue -> Objects.toString(paramItemValue, "")) .collect(Collectors.joining(",")); return service - .listBlobHierarchySegment(this.client.getUrl(), containerName, restype, comp, prefix, delimiter, marker, - maxresults, includeConverted, startFrom, timeout, this.client.getVersion(), requestId, accept, context) + .listBlobFlatSegmentApacheArrow(this.client.getUrl(), containerName, restype, comp, accept, prefix, marker, + maxresults, includeConverted, timeout, startFrom, endBefore, this.client.getVersion(), requestId, + context) .onErrorMap(BlobStorageExceptionInternal.class, ModelHelper::mapToBlobStorageException); } /** - * [Update] The List Blobs operation returns a list of the blobs under the specified container. + * The List Blobs operation returns a list of the blobs under the specified container. This operation is for Apache + * Arrow use case so response is returned as raw to be deserialized by the client. * * @param containerName The container name. - * @param delimiter 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. * @param prefix Filters the results to return only containers whose name begins with the specified prefix. * @param marker 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 @@ -6184,35 +6285,34 @@ public Response listBlobFlatSegmentNoCustomHeaders * 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. * @param include Include this parameter to specify one or more datasets to include in the response. - * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is - * supported; For recursive list, multiple entity levels are supported. (Inclusive). * @param timeout The timeout parameter is expressed in seconds. For more information, see <a * href="https://learn.microsoft.com/rest/api/storageservices/setting-timeouts-for-blob-service-operations">Setting * Timeouts for Blob Service Operations.</a>. + * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is + * supported; For recursive list, multiple entity levels are supported. (Inclusive). + * @param endBefore Specifies the relative path to end before list paths. (Exclusive). * @param requestId 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. * @throws IllegalArgumentException thrown if parameters fail the validation. * @throws BlobStorageExceptionInternal thrown if the request is rejected by server. * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. - * @return an enumeration of blobs on successful completion of {@link Mono}. + * @return the response. */ @ServiceMethod(returns = ReturnType.SINGLE) - public Mono listBlobHierarchySegmentAsync(String containerName, String delimiter, - String prefix, String marker, Integer maxresults, List include, String startFrom, - Integer timeout, String requestId) { - return listBlobHierarchySegmentWithResponseAsync(containerName, delimiter, prefix, marker, maxresults, include, - startFrom, timeout, requestId) + public Flux listBlobFlatSegmentApacheArrowAsync(String containerName, String prefix, String marker, + Integer maxresults, List include, Integer timeout, String startFrom, String endBefore, + String requestId) { + return listBlobFlatSegmentApacheArrowWithResponseAsync(containerName, prefix, marker, maxresults, include, + timeout, startFrom, endBefore, requestId) .onErrorMap(BlobStorageExceptionInternal.class, ModelHelper::mapToBlobStorageException) - .flatMap(res -> Mono.justOrEmpty(res.getValue())); + .flatMapMany(fluxByteBufferResponse -> fluxByteBufferResponse.getValue()); } /** - * [Update] The List Blobs operation returns a list of the blobs under the specified container. + * The List Blobs operation returns a list of the blobs under the specified container. This operation is for Apache + * Arrow use case so response is returned as raw to be deserialized by the client. * * @param containerName The container name. - * @param delimiter 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. * @param prefix Filters the results to return only containers whose name begins with the specified prefix. * @param marker 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 @@ -6225,36 +6325,35 @@ public Mono listBlobHierarchySegmentAsync(Str * 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. * @param include Include this parameter to specify one or more datasets to include in the response. - * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is - * supported; For recursive list, multiple entity levels are supported. (Inclusive). * @param timeout The timeout parameter is expressed in seconds. For more information, see <a * href="https://learn.microsoft.com/rest/api/storageservices/setting-timeouts-for-blob-service-operations">Setting * Timeouts for Blob Service Operations.</a>. + * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is + * supported; For recursive list, multiple entity levels are supported. (Inclusive). + * @param endBefore Specifies the relative path to end before list paths. (Exclusive). * @param requestId 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. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @throws BlobStorageExceptionInternal thrown if the request is rejected by server. * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. - * @return an enumeration of blobs on successful completion of {@link Mono}. + * @return the response. */ @ServiceMethod(returns = ReturnType.SINGLE) - public Mono listBlobHierarchySegmentAsync(String containerName, String delimiter, - String prefix, String marker, Integer maxresults, List include, String startFrom, - Integer timeout, String requestId, Context context) { - return listBlobHierarchySegmentWithResponseAsync(containerName, delimiter, prefix, marker, maxresults, include, - startFrom, timeout, requestId, context) + public Flux listBlobFlatSegmentApacheArrowAsync(String containerName, String prefix, String marker, + Integer maxresults, List include, Integer timeout, String startFrom, String endBefore, + String requestId, Context context) { + return listBlobFlatSegmentApacheArrowWithResponseAsync(containerName, prefix, marker, maxresults, include, + timeout, startFrom, endBefore, requestId, context) .onErrorMap(BlobStorageExceptionInternal.class, ModelHelper::mapToBlobStorageException) - .flatMap(res -> Mono.justOrEmpty(res.getValue())); + .flatMapMany(fluxByteBufferResponse -> fluxByteBufferResponse.getValue()); } /** - * [Update] The List Blobs operation returns a list of the blobs under the specified container. + * The List Blobs operation returns a list of the blobs under the specified container. This operation is for Apache + * Arrow use case so response is returned as raw to be deserialized by the client. * * @param containerName The container name. - * @param delimiter 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. * @param prefix Filters the results to return only containers whose name begins with the specified prefix. * @param marker 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 @@ -6267,35 +6366,34 @@ public Mono listBlobHierarchySegmentAsync(Str * 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. * @param include Include this parameter to specify one or more datasets to include in the response. - * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is - * supported; For recursive list, multiple entity levels are supported. (Inclusive). * @param timeout The timeout parameter is expressed in seconds. For more information, see <a * href="https://learn.microsoft.com/rest/api/storageservices/setting-timeouts-for-blob-service-operations">Setting * Timeouts for Blob Service Operations.</a>. + * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is + * supported; For recursive list, multiple entity levels are supported. (Inclusive). + * @param endBefore Specifies the relative path to end before list paths. (Exclusive). * @param requestId 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. * @throws IllegalArgumentException thrown if parameters fail the validation. * @throws BlobStorageExceptionInternal thrown if the request is rejected by server. * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. - * @return an enumeration of blobs along with {@link Response} on successful completion of {@link Mono}. + * @return the response body on successful completion of {@link Mono}. */ @ServiceMethod(returns = ReturnType.SINGLE) - public Mono> listBlobHierarchySegmentNoCustomHeadersWithResponseAsync( - String containerName, String delimiter, String prefix, String marker, Integer maxresults, - List include, String startFrom, Integer timeout, String requestId) { + public Mono listBlobFlatSegmentApacheArrowNoCustomHeadersWithResponseAsync(String containerName, + String prefix, String marker, Integer maxresults, List include, Integer timeout, + String startFrom, String endBefore, String requestId) { return FluxUtil - .withContext(context -> listBlobHierarchySegmentNoCustomHeadersWithResponseAsync(containerName, delimiter, - prefix, marker, maxresults, include, startFrom, timeout, requestId, context)) + .withContext(context -> listBlobFlatSegmentApacheArrowNoCustomHeadersWithResponseAsync(containerName, + prefix, marker, maxresults, include, timeout, startFrom, endBefore, requestId, context)) .onErrorMap(BlobStorageExceptionInternal.class, ModelHelper::mapToBlobStorageException); } /** - * [Update] The List Blobs operation returns a list of the blobs under the specified container. + * The List Blobs operation returns a list of the blobs under the specified container. This operation is for Apache + * Arrow use case so response is returned as raw to be deserialized by the client. * * @param containerName The container name. - * @param delimiter 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. * @param prefix Filters the results to return only containers whose name begins with the specified prefix. * @param marker 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 @@ -6308,45 +6406,44 @@ public Mono> listBlobHierarchySegmen * 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. * @param include Include this parameter to specify one or more datasets to include in the response. - * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is - * supported; For recursive list, multiple entity levels are supported. (Inclusive). * @param timeout The timeout parameter is expressed in seconds. For more information, see <a * href="https://learn.microsoft.com/rest/api/storageservices/setting-timeouts-for-blob-service-operations">Setting * Timeouts for Blob Service Operations.</a>. + * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is + * supported; For recursive list, multiple entity levels are supported. (Inclusive). + * @param endBefore Specifies the relative path to end before list paths. (Exclusive). * @param requestId 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. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @throws BlobStorageExceptionInternal thrown if the request is rejected by server. * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. - * @return an enumeration of blobs along with {@link Response} on successful completion of {@link Mono}. + * @return the response body on successful completion of {@link Mono}. */ @ServiceMethod(returns = ReturnType.SINGLE) - public Mono> listBlobHierarchySegmentNoCustomHeadersWithResponseAsync( - String containerName, String delimiter, String prefix, String marker, Integer maxresults, - List include, String startFrom, Integer timeout, String requestId, Context context) { + public Mono listBlobFlatSegmentApacheArrowNoCustomHeadersWithResponseAsync(String containerName, + String prefix, String marker, Integer maxresults, List include, Integer timeout, + String startFrom, String endBefore, String requestId, Context context) { final String restype = "container"; final String comp = "list"; - final String accept = "application/xml"; + final String accept = "application/vnd.apache.arrow.stream"; String includeConverted = (include == null) ? null : include.stream() .map(paramItemValue -> Objects.toString(paramItemValue, "")) .collect(Collectors.joining(",")); return service - .listBlobHierarchySegmentNoCustomHeaders(this.client.getUrl(), containerName, restype, comp, prefix, - delimiter, marker, maxresults, includeConverted, startFrom, timeout, this.client.getVersion(), - requestId, accept, context) + .listBlobFlatSegmentApacheArrowNoCustomHeaders(this.client.getUrl(), containerName, restype, comp, accept, + prefix, marker, maxresults, includeConverted, timeout, startFrom, endBefore, this.client.getVersion(), + requestId, context) .onErrorMap(BlobStorageExceptionInternal.class, ModelHelper::mapToBlobStorageException); } /** - * [Update] The List Blobs operation returns a list of the blobs under the specified container. + * The List Blobs operation returns a list of the blobs under the specified container. This operation is for Apache + * Arrow use case so response is returned as raw to be deserialized by the client. * * @param containerName The container name. - * @param delimiter 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. * @param prefix Filters the results to return only containers whose name begins with the specified prefix. * @param marker 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 @@ -6359,48 +6456,47 @@ public Mono> listBlobHierarchySegmen * 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. * @param include Include this parameter to specify one or more datasets to include in the response. - * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is - * supported; For recursive list, multiple entity levels are supported. (Inclusive). * @param timeout The timeout parameter is expressed in seconds. For more information, see <a * href="https://learn.microsoft.com/rest/api/storageservices/setting-timeouts-for-blob-service-operations">Setting * Timeouts for Blob Service Operations.</a>. + * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is + * supported; For recursive list, multiple entity levels are supported. (Inclusive). + * @param endBefore Specifies the relative path to end before list paths. (Exclusive). * @param requestId 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. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @throws BlobStorageExceptionInternal thrown if the request is rejected by server. * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. - * @return an enumeration of blobs along with {@link ResponseBase}. + * @return the response body along with {@link ResponseBase}. */ @ServiceMethod(returns = ReturnType.SINGLE) - public ResponseBase - listBlobHierarchySegmentWithResponse(String containerName, String delimiter, String prefix, String marker, - Integer maxresults, List include, String startFrom, Integer timeout, String requestId, - Context context) { + public ResponseBase + listBlobFlatSegmentApacheArrowWithResponse(String containerName, String prefix, String marker, + Integer maxresults, List include, Integer timeout, String startFrom, String endBefore, + String requestId, Context context) { try { final String restype = "container"; final String comp = "list"; - final String accept = "application/xml"; + final String accept = "application/vnd.apache.arrow.stream"; String includeConverted = (include == null) ? null : include.stream() .map(paramItemValue -> Objects.toString(paramItemValue, "")) .collect(Collectors.joining(",")); - return service.listBlobHierarchySegmentSync(this.client.getUrl(), containerName, restype, comp, prefix, - delimiter, marker, maxresults, includeConverted, startFrom, timeout, this.client.getVersion(), - requestId, accept, context); + return service.listBlobFlatSegmentApacheArrowSync(this.client.getUrl(), containerName, restype, comp, + accept, prefix, marker, maxresults, includeConverted, timeout, startFrom, endBefore, + this.client.getVersion(), requestId, context); } catch (BlobStorageExceptionInternal internalException) { throw ModelHelper.mapToBlobStorageException(internalException); } } /** - * [Update] The List Blobs operation returns a list of the blobs under the specified container. + * The List Blobs operation returns a list of the blobs under the specified container. This operation is for Apache + * Arrow use case so response is returned as raw to be deserialized by the client. * * @param containerName The container name. - * @param delimiter 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. * @param prefix Filters the results to return only containers whose name begins with the specified prefix. * @param marker 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 @@ -6413,37 +6509,36 @@ public Mono> listBlobHierarchySegmen * 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. * @param include Include this parameter to specify one or more datasets to include in the response. - * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is - * supported; For recursive list, multiple entity levels are supported. (Inclusive). * @param timeout The timeout parameter is expressed in seconds. For more information, see <a * href="https://learn.microsoft.com/rest/api/storageservices/setting-timeouts-for-blob-service-operations">Setting * Timeouts for Blob Service Operations.</a>. + * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is + * supported; For recursive list, multiple entity levels are supported. (Inclusive). + * @param endBefore Specifies the relative path to end before list paths. (Exclusive). * @param requestId 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. * @throws IllegalArgumentException thrown if parameters fail the validation. * @throws BlobStorageExceptionInternal thrown if the request is rejected by server. * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. - * @return an enumeration of blobs. + * @return the response. */ @ServiceMethod(returns = ReturnType.SINGLE) - public ListBlobsHierarchySegmentResponse listBlobHierarchySegment(String containerName, String delimiter, - String prefix, String marker, Integer maxresults, List include, String startFrom, - Integer timeout, String requestId) { + public InputStream listBlobFlatSegmentApacheArrow(String containerName, String prefix, String marker, + Integer maxresults, List include, Integer timeout, String startFrom, String endBefore, + String requestId) { try { - return listBlobHierarchySegmentWithResponse(containerName, delimiter, prefix, marker, maxresults, include, - startFrom, timeout, requestId, Context.NONE).getValue(); + return listBlobFlatSegmentApacheArrowWithResponse(containerName, prefix, marker, maxresults, include, + timeout, startFrom, endBefore, requestId, Context.NONE).getValue(); } catch (BlobStorageExceptionInternal internalException) { throw ModelHelper.mapToBlobStorageException(internalException); } } /** - * [Update] The List Blobs operation returns a list of the blobs under the specified container. + * The List Blobs operation returns a list of the blobs under the specified container. This operation is for Apache + * Arrow use case so response is returned as raw to be deserialized by the client. * * @param containerName The container name. - * @param delimiter 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. * @param prefix Filters the results to return only containers whose name begins with the specified prefix. * @param marker 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 @@ -6456,35 +6551,892 @@ public ListBlobsHierarchySegmentResponse listBlobHierarchySegment(String contain * 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. * @param include Include this parameter to specify one or more datasets to include in the response. - * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is - * supported; For recursive list, multiple entity levels are supported. (Inclusive). * @param timeout The timeout parameter is expressed in seconds. For more information, see <a * href="https://learn.microsoft.com/rest/api/storageservices/setting-timeouts-for-blob-service-operations">Setting * Timeouts for Blob Service Operations.</a>. + * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is + * supported; For recursive list, multiple entity levels are supported. (Inclusive). + * @param endBefore Specifies the relative path to end before list paths. (Exclusive). * @param requestId 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. * @param context The context to associate with this operation. * @throws IllegalArgumentException thrown if parameters fail the validation. * @throws BlobStorageExceptionInternal thrown if the request is rejected by server. * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. - * @return an enumeration of blobs along with {@link Response}. + * @return the response body along with {@link Response}. */ @ServiceMethod(returns = ReturnType.SINGLE) - public Response listBlobHierarchySegmentNoCustomHeadersWithResponse( - String containerName, String delimiter, String prefix, String marker, Integer maxresults, - List include, String startFrom, Integer timeout, String requestId, Context context) { + public Response listBlobFlatSegmentApacheArrowNoCustomHeadersWithResponse(String containerName, + String prefix, String marker, Integer maxresults, List include, Integer timeout, + String startFrom, String endBefore, String requestId, Context context) { try { final String restype = "container"; final String comp = "list"; - final String accept = "application/xml"; + final String accept = "application/vnd.apache.arrow.stream"; String includeConverted = (include == null) ? null : include.stream() .map(paramItemValue -> Objects.toString(paramItemValue, "")) .collect(Collectors.joining(",")); - return service.listBlobHierarchySegmentNoCustomHeadersSync(this.client.getUrl(), containerName, restype, - comp, prefix, delimiter, marker, maxresults, includeConverted, startFrom, timeout, - this.client.getVersion(), requestId, accept, context); + return service.listBlobFlatSegmentApacheArrowNoCustomHeadersSync(this.client.getUrl(), containerName, + restype, comp, accept, prefix, marker, maxresults, includeConverted, timeout, startFrom, endBefore, + this.client.getVersion(), requestId, context); + } catch (BlobStorageExceptionInternal internalException) { + throw ModelHelper.mapToBlobStorageException(internalException); + } + } + + /** + * [Update] The List Blobs operation returns a list of the blobs under the specified container. + * + * @param containerName The container name. + * @param delimiter 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. + * @param prefix Filters the results to return only containers whose name begins with the specified prefix. + * @param marker 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. + * @param maxresults 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. + * @param include Include this parameter to specify one or more datasets to include in the response. + * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is + * supported; For recursive list, multiple entity levels are supported. (Inclusive). + * @param timeout The timeout parameter is expressed in seconds. For more information, see <a + * href="https://learn.microsoft.com/rest/api/storageservices/setting-timeouts-for-blob-service-operations">Setting + * Timeouts for Blob Service Operations.</a>. + * @param requestId 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. + * @throws IllegalArgumentException thrown if parameters fail the validation. + * @throws BlobStorageExceptionInternal thrown if the request is rejected by server. + * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. + * @return an enumeration of blobs along with {@link ResponseBase} on successful completion of {@link Mono}. + */ + @ServiceMethod(returns = ReturnType.SINGLE) + public Mono> + listBlobHierarchySegmentWithResponseAsync(String containerName, String delimiter, String prefix, String marker, + Integer maxresults, List include, String startFrom, Integer timeout, + String requestId) { + return FluxUtil + .withContext(context -> listBlobHierarchySegmentWithResponseAsync(containerName, delimiter, prefix, marker, + maxresults, include, startFrom, timeout, requestId, context)) + .onErrorMap(BlobStorageExceptionInternal.class, ModelHelper::mapToBlobStorageException); + } + + /** + * [Update] The List Blobs operation returns a list of the blobs under the specified container. + * + * @param containerName The container name. + * @param delimiter 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. + * @param prefix Filters the results to return only containers whose name begins with the specified prefix. + * @param marker 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. + * @param maxresults 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. + * @param include Include this parameter to specify one or more datasets to include in the response. + * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is + * supported; For recursive list, multiple entity levels are supported. (Inclusive). + * @param timeout The timeout parameter is expressed in seconds. For more information, see <a + * href="https://learn.microsoft.com/rest/api/storageservices/setting-timeouts-for-blob-service-operations">Setting + * Timeouts for Blob Service Operations.</a>. + * @param requestId 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. + * @param context The context to associate with this operation. + * @throws IllegalArgumentException thrown if parameters fail the validation. + * @throws BlobStorageExceptionInternal thrown if the request is rejected by server. + * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. + * @return an enumeration of blobs along with {@link ResponseBase} on successful completion of {@link Mono}. + */ + @ServiceMethod(returns = ReturnType.SINGLE) + public Mono> + listBlobHierarchySegmentWithResponseAsync(String containerName, String delimiter, String prefix, String marker, + Integer maxresults, List include, String startFrom, Integer timeout, String requestId, + Context context) { + final String restype = "container"; + final String comp = "list"; + final String accept = "application/xml"; + String includeConverted = (include == null) + ? null + : include.stream() + .map(paramItemValue -> Objects.toString(paramItemValue, "")) + .collect(Collectors.joining(",")); + return service + .listBlobHierarchySegment(this.client.getUrl(), containerName, restype, comp, prefix, delimiter, marker, + maxresults, includeConverted, startFrom, timeout, this.client.getVersion(), requestId, accept, context) + .onErrorMap(BlobStorageExceptionInternal.class, ModelHelper::mapToBlobStorageException); + } + + /** + * [Update] The List Blobs operation returns a list of the blobs under the specified container. + * + * @param containerName The container name. + * @param delimiter 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. + * @param prefix Filters the results to return only containers whose name begins with the specified prefix. + * @param marker 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. + * @param maxresults 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. + * @param include Include this parameter to specify one or more datasets to include in the response. + * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is + * supported; For recursive list, multiple entity levels are supported. (Inclusive). + * @param timeout The timeout parameter is expressed in seconds. For more information, see <a + * href="https://learn.microsoft.com/rest/api/storageservices/setting-timeouts-for-blob-service-operations">Setting + * Timeouts for Blob Service Operations.</a>. + * @param requestId 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. + * @throws IllegalArgumentException thrown if parameters fail the validation. + * @throws BlobStorageExceptionInternal thrown if the request is rejected by server. + * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. + * @return an enumeration of blobs on successful completion of {@link Mono}. + */ + @ServiceMethod(returns = ReturnType.SINGLE) + public Mono listBlobHierarchySegmentAsync(String containerName, String delimiter, + String prefix, String marker, Integer maxresults, List include, String startFrom, + Integer timeout, String requestId) { + return listBlobHierarchySegmentWithResponseAsync(containerName, delimiter, prefix, marker, maxresults, include, + startFrom, timeout, requestId) + .onErrorMap(BlobStorageExceptionInternal.class, ModelHelper::mapToBlobStorageException) + .flatMap(res -> Mono.justOrEmpty(res.getValue())); + } + + /** + * [Update] The List Blobs operation returns a list of the blobs under the specified container. + * + * @param containerName The container name. + * @param delimiter 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. + * @param prefix Filters the results to return only containers whose name begins with the specified prefix. + * @param marker 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. + * @param maxresults 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. + * @param include Include this parameter to specify one or more datasets to include in the response. + * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is + * supported; For recursive list, multiple entity levels are supported. (Inclusive). + * @param timeout The timeout parameter is expressed in seconds. For more information, see <a + * href="https://learn.microsoft.com/rest/api/storageservices/setting-timeouts-for-blob-service-operations">Setting + * Timeouts for Blob Service Operations.</a>. + * @param requestId 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. + * @param context The context to associate with this operation. + * @throws IllegalArgumentException thrown if parameters fail the validation. + * @throws BlobStorageExceptionInternal thrown if the request is rejected by server. + * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. + * @return an enumeration of blobs on successful completion of {@link Mono}. + */ + @ServiceMethod(returns = ReturnType.SINGLE) + public Mono listBlobHierarchySegmentAsync(String containerName, String delimiter, + String prefix, String marker, Integer maxresults, List include, String startFrom, + Integer timeout, String requestId, Context context) { + return listBlobHierarchySegmentWithResponseAsync(containerName, delimiter, prefix, marker, maxresults, include, + startFrom, timeout, requestId, context) + .onErrorMap(BlobStorageExceptionInternal.class, ModelHelper::mapToBlobStorageException) + .flatMap(res -> Mono.justOrEmpty(res.getValue())); + } + + /** + * [Update] The List Blobs operation returns a list of the blobs under the specified container. + * + * @param containerName The container name. + * @param delimiter 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. + * @param prefix Filters the results to return only containers whose name begins with the specified prefix. + * @param marker 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. + * @param maxresults 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. + * @param include Include this parameter to specify one or more datasets to include in the response. + * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is + * supported; For recursive list, multiple entity levels are supported. (Inclusive). + * @param timeout The timeout parameter is expressed in seconds. For more information, see <a + * href="https://learn.microsoft.com/rest/api/storageservices/setting-timeouts-for-blob-service-operations">Setting + * Timeouts for Blob Service Operations.</a>. + * @param requestId 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. + * @throws IllegalArgumentException thrown if parameters fail the validation. + * @throws BlobStorageExceptionInternal thrown if the request is rejected by server. + * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. + * @return an enumeration of blobs along with {@link Response} on successful completion of {@link Mono}. + */ + @ServiceMethod(returns = ReturnType.SINGLE) + public Mono> listBlobHierarchySegmentNoCustomHeadersWithResponseAsync( + String containerName, String delimiter, String prefix, String marker, Integer maxresults, + List include, String startFrom, Integer timeout, String requestId) { + return FluxUtil + .withContext(context -> listBlobHierarchySegmentNoCustomHeadersWithResponseAsync(containerName, delimiter, + prefix, marker, maxresults, include, startFrom, timeout, requestId, context)) + .onErrorMap(BlobStorageExceptionInternal.class, ModelHelper::mapToBlobStorageException); + } + + /** + * [Update] The List Blobs operation returns a list of the blobs under the specified container. + * + * @param containerName The container name. + * @param delimiter 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. + * @param prefix Filters the results to return only containers whose name begins with the specified prefix. + * @param marker 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. + * @param maxresults 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. + * @param include Include this parameter to specify one or more datasets to include in the response. + * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is + * supported; For recursive list, multiple entity levels are supported. (Inclusive). + * @param timeout The timeout parameter is expressed in seconds. For more information, see <a + * href="https://learn.microsoft.com/rest/api/storageservices/setting-timeouts-for-blob-service-operations">Setting + * Timeouts for Blob Service Operations.</a>. + * @param requestId 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. + * @param context The context to associate with this operation. + * @throws IllegalArgumentException thrown if parameters fail the validation. + * @throws BlobStorageExceptionInternal thrown if the request is rejected by server. + * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. + * @return an enumeration of blobs along with {@link Response} on successful completion of {@link Mono}. + */ + @ServiceMethod(returns = ReturnType.SINGLE) + public Mono> listBlobHierarchySegmentNoCustomHeadersWithResponseAsync( + String containerName, String delimiter, String prefix, String marker, Integer maxresults, + List include, String startFrom, Integer timeout, String requestId, Context context) { + final String restype = "container"; + final String comp = "list"; + final String accept = "application/xml"; + String includeConverted = (include == null) + ? null + : include.stream() + .map(paramItemValue -> Objects.toString(paramItemValue, "")) + .collect(Collectors.joining(",")); + return service + .listBlobHierarchySegmentNoCustomHeaders(this.client.getUrl(), containerName, restype, comp, prefix, + delimiter, marker, maxresults, includeConverted, startFrom, timeout, this.client.getVersion(), + requestId, accept, context) + .onErrorMap(BlobStorageExceptionInternal.class, ModelHelper::mapToBlobStorageException); + } + + /** + * [Update] The List Blobs operation returns a list of the blobs under the specified container. + * + * @param containerName The container name. + * @param delimiter 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. + * @param prefix Filters the results to return only containers whose name begins with the specified prefix. + * @param marker 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. + * @param maxresults 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. + * @param include Include this parameter to specify one or more datasets to include in the response. + * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is + * supported; For recursive list, multiple entity levels are supported. (Inclusive). + * @param timeout The timeout parameter is expressed in seconds. For more information, see <a + * href="https://learn.microsoft.com/rest/api/storageservices/setting-timeouts-for-blob-service-operations">Setting + * Timeouts for Blob Service Operations.</a>. + * @param requestId 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. + * @param context The context to associate with this operation. + * @throws IllegalArgumentException thrown if parameters fail the validation. + * @throws BlobStorageExceptionInternal thrown if the request is rejected by server. + * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. + * @return an enumeration of blobs along with {@link ResponseBase}. + */ + @ServiceMethod(returns = ReturnType.SINGLE) + public ResponseBase + listBlobHierarchySegmentWithResponse(String containerName, String delimiter, String prefix, String marker, + Integer maxresults, List include, String startFrom, Integer timeout, String requestId, + Context context) { + try { + final String restype = "container"; + final String comp = "list"; + final String accept = "application/xml"; + String includeConverted = (include == null) + ? null + : include.stream() + .map(paramItemValue -> Objects.toString(paramItemValue, "")) + .collect(Collectors.joining(",")); + return service.listBlobHierarchySegmentSync(this.client.getUrl(), containerName, restype, comp, prefix, + delimiter, marker, maxresults, includeConverted, startFrom, timeout, this.client.getVersion(), + requestId, accept, context); + } catch (BlobStorageExceptionInternal internalException) { + throw ModelHelper.mapToBlobStorageException(internalException); + } + } + + /** + * [Update] The List Blobs operation returns a list of the blobs under the specified container. + * + * @param containerName The container name. + * @param delimiter 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. + * @param prefix Filters the results to return only containers whose name begins with the specified prefix. + * @param marker 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. + * @param maxresults 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. + * @param include Include this parameter to specify one or more datasets to include in the response. + * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is + * supported; For recursive list, multiple entity levels are supported. (Inclusive). + * @param timeout The timeout parameter is expressed in seconds. For more information, see <a + * href="https://learn.microsoft.com/rest/api/storageservices/setting-timeouts-for-blob-service-operations">Setting + * Timeouts for Blob Service Operations.</a>. + * @param requestId 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. + * @throws IllegalArgumentException thrown if parameters fail the validation. + * @throws BlobStorageExceptionInternal thrown if the request is rejected by server. + * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. + * @return an enumeration of blobs. + */ + @ServiceMethod(returns = ReturnType.SINGLE) + public ListBlobsHierarchySegmentResponse listBlobHierarchySegment(String containerName, String delimiter, + String prefix, String marker, Integer maxresults, List include, String startFrom, + Integer timeout, String requestId) { + try { + return listBlobHierarchySegmentWithResponse(containerName, delimiter, prefix, marker, maxresults, include, + startFrom, timeout, requestId, Context.NONE).getValue(); + } catch (BlobStorageExceptionInternal internalException) { + throw ModelHelper.mapToBlobStorageException(internalException); + } + } + + /** + * [Update] The List Blobs operation returns a list of the blobs under the specified container. + * + * @param containerName The container name. + * @param delimiter 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. + * @param prefix Filters the results to return only containers whose name begins with the specified prefix. + * @param marker 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. + * @param maxresults 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. + * @param include Include this parameter to specify one or more datasets to include in the response. + * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is + * supported; For recursive list, multiple entity levels are supported. (Inclusive). + * @param timeout The timeout parameter is expressed in seconds. For more information, see <a + * href="https://learn.microsoft.com/rest/api/storageservices/setting-timeouts-for-blob-service-operations">Setting + * Timeouts for Blob Service Operations.</a>. + * @param requestId 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. + * @param context The context to associate with this operation. + * @throws IllegalArgumentException thrown if parameters fail the validation. + * @throws BlobStorageExceptionInternal thrown if the request is rejected by server. + * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. + * @return an enumeration of blobs along with {@link Response}. + */ + @ServiceMethod(returns = ReturnType.SINGLE) + public Response listBlobHierarchySegmentNoCustomHeadersWithResponse( + String containerName, String delimiter, String prefix, String marker, Integer maxresults, + List include, String startFrom, Integer timeout, String requestId, Context context) { + try { + final String restype = "container"; + final String comp = "list"; + final String accept = "application/xml"; + String includeConverted = (include == null) + ? null + : include.stream() + .map(paramItemValue -> Objects.toString(paramItemValue, "")) + .collect(Collectors.joining(",")); + return service.listBlobHierarchySegmentNoCustomHeadersSync(this.client.getUrl(), containerName, restype, + comp, prefix, delimiter, marker, maxresults, includeConverted, startFrom, timeout, + this.client.getVersion(), requestId, accept, context); + } catch (BlobStorageExceptionInternal internalException) { + throw ModelHelper.mapToBlobStorageException(internalException); + } + } + + /** + * [Update] The List Blobs operation returns a list of the blobs under the specified container. This operation is + * for Apache Arrow use case so response is returned as raw to be deserialized by the client. + * + * @param containerName The container name. + * @param delimiter 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. + * @param prefix Filters the results to return only containers whose name begins with the specified prefix. + * @param marker 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. + * @param maxresults 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. + * @param include Include this parameter to specify one or more datasets to include in the response. + * @param timeout The timeout parameter is expressed in seconds. For more information, see <a + * href="https://learn.microsoft.com/rest/api/storageservices/setting-timeouts-for-blob-service-operations">Setting + * Timeouts for Blob Service Operations.</a>. + * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is + * supported; For recursive list, multiple entity levels are supported. (Inclusive). + * @param endBefore Specifies the relative path to end before list paths. (Exclusive). + * @param requestId 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. + * @throws IllegalArgumentException thrown if parameters fail the validation. + * @throws BlobStorageExceptionInternal thrown if the request is rejected by server. + * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. + * @return the response body along with {@link ResponseBase} on successful completion of {@link Mono}. + */ + @ServiceMethod(returns = ReturnType.SINGLE) + public Mono>> + listBlobHierarchySegmentApacheArrowWithResponseAsync(String containerName, String delimiter, String prefix, + String marker, Integer maxresults, List include, Integer timeout, String startFrom, + String endBefore, String requestId) { + return FluxUtil + .withContext(context -> listBlobHierarchySegmentApacheArrowWithResponseAsync(containerName, delimiter, + prefix, marker, maxresults, include, timeout, startFrom, endBefore, requestId, context)) + .onErrorMap(BlobStorageExceptionInternal.class, ModelHelper::mapToBlobStorageException); + } + + /** + * [Update] The List Blobs operation returns a list of the blobs under the specified container. This operation is + * for Apache Arrow use case so response is returned as raw to be deserialized by the client. + * + * @param containerName The container name. + * @param delimiter 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. + * @param prefix Filters the results to return only containers whose name begins with the specified prefix. + * @param marker 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. + * @param maxresults 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. + * @param include Include this parameter to specify one or more datasets to include in the response. + * @param timeout The timeout parameter is expressed in seconds. For more information, see <a + * href="https://learn.microsoft.com/rest/api/storageservices/setting-timeouts-for-blob-service-operations">Setting + * Timeouts for Blob Service Operations.</a>. + * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is + * supported; For recursive list, multiple entity levels are supported. (Inclusive). + * @param endBefore Specifies the relative path to end before list paths. (Exclusive). + * @param requestId 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. + * @param context The context to associate with this operation. + * @throws IllegalArgumentException thrown if parameters fail the validation. + * @throws BlobStorageExceptionInternal thrown if the request is rejected by server. + * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. + * @return the response body along with {@link ResponseBase} on successful completion of {@link Mono}. + */ + @ServiceMethod(returns = ReturnType.SINGLE) + public Mono>> + listBlobHierarchySegmentApacheArrowWithResponseAsync(String containerName, String delimiter, String prefix, + String marker, Integer maxresults, List include, Integer timeout, String startFrom, + String endBefore, String requestId, Context context) { + final String restype = "container"; + final String comp = "list"; + final String accept = "application/vnd.apache.arrow.stream"; + String includeConverted = (include == null) + ? null + : include.stream() + .map(paramItemValue -> Objects.toString(paramItemValue, "")) + .collect(Collectors.joining(",")); + return service + .listBlobHierarchySegmentApacheArrow(this.client.getUrl(), containerName, restype, comp, accept, prefix, + delimiter, marker, maxresults, includeConverted, timeout, startFrom, endBefore, + this.client.getVersion(), requestId, context) + .onErrorMap(BlobStorageExceptionInternal.class, ModelHelper::mapToBlobStorageException); + } + + /** + * [Update] The List Blobs operation returns a list of the blobs under the specified container. This operation is + * for Apache Arrow use case so response is returned as raw to be deserialized by the client. + * + * @param containerName The container name. + * @param delimiter 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. + * @param prefix Filters the results to return only containers whose name begins with the specified prefix. + * @param marker 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. + * @param maxresults 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. + * @param include Include this parameter to specify one or more datasets to include in the response. + * @param timeout The timeout parameter is expressed in seconds. For more information, see <a + * href="https://learn.microsoft.com/rest/api/storageservices/setting-timeouts-for-blob-service-operations">Setting + * Timeouts for Blob Service Operations.</a>. + * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is + * supported; For recursive list, multiple entity levels are supported. (Inclusive). + * @param endBefore Specifies the relative path to end before list paths. (Exclusive). + * @param requestId 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. + * @throws IllegalArgumentException thrown if parameters fail the validation. + * @throws BlobStorageExceptionInternal thrown if the request is rejected by server. + * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. + * @return the response. + */ + @ServiceMethod(returns = ReturnType.SINGLE) + public Flux listBlobHierarchySegmentApacheArrowAsync(String containerName, String delimiter, + String prefix, String marker, Integer maxresults, List include, Integer timeout, + String startFrom, String endBefore, String requestId) { + return listBlobHierarchySegmentApacheArrowWithResponseAsync(containerName, delimiter, prefix, marker, + maxresults, include, timeout, startFrom, endBefore, requestId) + .onErrorMap(BlobStorageExceptionInternal.class, ModelHelper::mapToBlobStorageException) + .flatMapMany(fluxByteBufferResponse -> fluxByteBufferResponse.getValue()); + } + + /** + * [Update] The List Blobs operation returns a list of the blobs under the specified container. This operation is + * for Apache Arrow use case so response is returned as raw to be deserialized by the client. + * + * @param containerName The container name. + * @param delimiter 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. + * @param prefix Filters the results to return only containers whose name begins with the specified prefix. + * @param marker 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. + * @param maxresults 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. + * @param include Include this parameter to specify one or more datasets to include in the response. + * @param timeout The timeout parameter is expressed in seconds. For more information, see <a + * href="https://learn.microsoft.com/rest/api/storageservices/setting-timeouts-for-blob-service-operations">Setting + * Timeouts for Blob Service Operations.</a>. + * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is + * supported; For recursive list, multiple entity levels are supported. (Inclusive). + * @param endBefore Specifies the relative path to end before list paths. (Exclusive). + * @param requestId 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. + * @param context The context to associate with this operation. + * @throws IllegalArgumentException thrown if parameters fail the validation. + * @throws BlobStorageExceptionInternal thrown if the request is rejected by server. + * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. + * @return the response. + */ + @ServiceMethod(returns = ReturnType.SINGLE) + public Flux listBlobHierarchySegmentApacheArrowAsync(String containerName, String delimiter, + String prefix, String marker, Integer maxresults, List include, Integer timeout, + String startFrom, String endBefore, String requestId, Context context) { + return listBlobHierarchySegmentApacheArrowWithResponseAsync(containerName, delimiter, prefix, marker, + maxresults, include, timeout, startFrom, endBefore, requestId, context) + .onErrorMap(BlobStorageExceptionInternal.class, ModelHelper::mapToBlobStorageException) + .flatMapMany(fluxByteBufferResponse -> fluxByteBufferResponse.getValue()); + } + + /** + * [Update] The List Blobs operation returns a list of the blobs under the specified container. This operation is + * for Apache Arrow use case so response is returned as raw to be deserialized by the client. + * + * @param containerName The container name. + * @param delimiter 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. + * @param prefix Filters the results to return only containers whose name begins with the specified prefix. + * @param marker 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. + * @param maxresults 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. + * @param include Include this parameter to specify one or more datasets to include in the response. + * @param timeout The timeout parameter is expressed in seconds. For more information, see <a + * href="https://learn.microsoft.com/rest/api/storageservices/setting-timeouts-for-blob-service-operations">Setting + * Timeouts for Blob Service Operations.</a>. + * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is + * supported; For recursive list, multiple entity levels are supported. (Inclusive). + * @param endBefore Specifies the relative path to end before list paths. (Exclusive). + * @param requestId 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. + * @throws IllegalArgumentException thrown if parameters fail the validation. + * @throws BlobStorageExceptionInternal thrown if the request is rejected by server. + * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. + * @return the response body on successful completion of {@link Mono}. + */ + @ServiceMethod(returns = ReturnType.SINGLE) + public Mono listBlobHierarchySegmentApacheArrowNoCustomHeadersWithResponseAsync( + String containerName, String delimiter, String prefix, String marker, Integer maxresults, + List include, Integer timeout, String startFrom, String endBefore, String requestId) { + return FluxUtil + .withContext(context -> listBlobHierarchySegmentApacheArrowNoCustomHeadersWithResponseAsync(containerName, + delimiter, prefix, marker, maxresults, include, timeout, startFrom, endBefore, requestId, context)) + .onErrorMap(BlobStorageExceptionInternal.class, ModelHelper::mapToBlobStorageException); + } + + /** + * [Update] The List Blobs operation returns a list of the blobs under the specified container. This operation is + * for Apache Arrow use case so response is returned as raw to be deserialized by the client. + * + * @param containerName The container name. + * @param delimiter 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. + * @param prefix Filters the results to return only containers whose name begins with the specified prefix. + * @param marker 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. + * @param maxresults 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. + * @param include Include this parameter to specify one or more datasets to include in the response. + * @param timeout The timeout parameter is expressed in seconds. For more information, see <a + * href="https://learn.microsoft.com/rest/api/storageservices/setting-timeouts-for-blob-service-operations">Setting + * Timeouts for Blob Service Operations.</a>. + * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is + * supported; For recursive list, multiple entity levels are supported. (Inclusive). + * @param endBefore Specifies the relative path to end before list paths. (Exclusive). + * @param requestId 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. + * @param context The context to associate with this operation. + * @throws IllegalArgumentException thrown if parameters fail the validation. + * @throws BlobStorageExceptionInternal thrown if the request is rejected by server. + * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. + * @return the response body on successful completion of {@link Mono}. + */ + @ServiceMethod(returns = ReturnType.SINGLE) + public Mono listBlobHierarchySegmentApacheArrowNoCustomHeadersWithResponseAsync( + String containerName, String delimiter, String prefix, String marker, Integer maxresults, + List include, Integer timeout, String startFrom, String endBefore, String requestId, + Context context) { + final String restype = "container"; + final String comp = "list"; + final String accept = "application/vnd.apache.arrow.stream"; + String includeConverted = (include == null) + ? null + : include.stream() + .map(paramItemValue -> Objects.toString(paramItemValue, "")) + .collect(Collectors.joining(",")); + return service + .listBlobHierarchySegmentApacheArrowNoCustomHeaders(this.client.getUrl(), containerName, restype, comp, + accept, prefix, delimiter, marker, maxresults, includeConverted, timeout, startFrom, endBefore, + this.client.getVersion(), requestId, context) + .onErrorMap(BlobStorageExceptionInternal.class, ModelHelper::mapToBlobStorageException); + } + + /** + * [Update] The List Blobs operation returns a list of the blobs under the specified container. This operation is + * for Apache Arrow use case so response is returned as raw to be deserialized by the client. + * + * @param containerName The container name. + * @param delimiter 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. + * @param prefix Filters the results to return only containers whose name begins with the specified prefix. + * @param marker 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. + * @param maxresults 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. + * @param include Include this parameter to specify one or more datasets to include in the response. + * @param timeout The timeout parameter is expressed in seconds. For more information, see <a + * href="https://learn.microsoft.com/rest/api/storageservices/setting-timeouts-for-blob-service-operations">Setting + * Timeouts for Blob Service Operations.</a>. + * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is + * supported; For recursive list, multiple entity levels are supported. (Inclusive). + * @param endBefore Specifies the relative path to end before list paths. (Exclusive). + * @param requestId 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. + * @param context The context to associate with this operation. + * @throws IllegalArgumentException thrown if parameters fail the validation. + * @throws BlobStorageExceptionInternal thrown if the request is rejected by server. + * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. + * @return the response body along with {@link ResponseBase}. + */ + @ServiceMethod(returns = ReturnType.SINGLE) + public ResponseBase + listBlobHierarchySegmentApacheArrowWithResponse(String containerName, String delimiter, String prefix, + String marker, Integer maxresults, List include, Integer timeout, String startFrom, + String endBefore, String requestId, Context context) { + try { + final String restype = "container"; + final String comp = "list"; + final String accept = "application/vnd.apache.arrow.stream"; + String includeConverted = (include == null) + ? null + : include.stream() + .map(paramItemValue -> Objects.toString(paramItemValue, "")) + .collect(Collectors.joining(",")); + return service.listBlobHierarchySegmentApacheArrowSync(this.client.getUrl(), containerName, restype, comp, + accept, prefix, delimiter, marker, maxresults, includeConverted, timeout, startFrom, endBefore, + this.client.getVersion(), requestId, context); + } catch (BlobStorageExceptionInternal internalException) { + throw ModelHelper.mapToBlobStorageException(internalException); + } + } + + /** + * [Update] The List Blobs operation returns a list of the blobs under the specified container. This operation is + * for Apache Arrow use case so response is returned as raw to be deserialized by the client. + * + * @param containerName The container name. + * @param delimiter 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. + * @param prefix Filters the results to return only containers whose name begins with the specified prefix. + * @param marker 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. + * @param maxresults 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. + * @param include Include this parameter to specify one or more datasets to include in the response. + * @param timeout The timeout parameter is expressed in seconds. For more information, see <a + * href="https://learn.microsoft.com/rest/api/storageservices/setting-timeouts-for-blob-service-operations">Setting + * Timeouts for Blob Service Operations.</a>. + * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is + * supported; For recursive list, multiple entity levels are supported. (Inclusive). + * @param endBefore Specifies the relative path to end before list paths. (Exclusive). + * @param requestId 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. + * @throws IllegalArgumentException thrown if parameters fail the validation. + * @throws BlobStorageExceptionInternal thrown if the request is rejected by server. + * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. + * @return the response. + */ + @ServiceMethod(returns = ReturnType.SINGLE) + public InputStream listBlobHierarchySegmentApacheArrow(String containerName, String delimiter, String prefix, + String marker, Integer maxresults, List include, Integer timeout, String startFrom, + String endBefore, String requestId) { + try { + return listBlobHierarchySegmentApacheArrowWithResponse(containerName, delimiter, prefix, marker, maxresults, + include, timeout, startFrom, endBefore, requestId, Context.NONE).getValue(); + } catch (BlobStorageExceptionInternal internalException) { + throw ModelHelper.mapToBlobStorageException(internalException); + } + } + + /** + * [Update] The List Blobs operation returns a list of the blobs under the specified container. This operation is + * for Apache Arrow use case so response is returned as raw to be deserialized by the client. + * + * @param containerName The container name. + * @param delimiter 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. + * @param prefix Filters the results to return only containers whose name begins with the specified prefix. + * @param marker 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. + * @param maxresults 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. + * @param include Include this parameter to specify one or more datasets to include in the response. + * @param timeout The timeout parameter is expressed in seconds. For more information, see <a + * href="https://learn.microsoft.com/rest/api/storageservices/setting-timeouts-for-blob-service-operations">Setting + * Timeouts for Blob Service Operations.</a>. + * @param startFrom Specifies the relative path to list paths from. For non-recursive list, only one entity level is + * supported; For recursive list, multiple entity levels are supported. (Inclusive). + * @param endBefore Specifies the relative path to end before list paths. (Exclusive). + * @param requestId 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. + * @param context The context to associate with this operation. + * @throws IllegalArgumentException thrown if parameters fail the validation. + * @throws BlobStorageExceptionInternal thrown if the request is rejected by server. + * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. + * @return the response body along with {@link Response}. + */ + @ServiceMethod(returns = ReturnType.SINGLE) + public Response listBlobHierarchySegmentApacheArrowNoCustomHeadersWithResponse(String containerName, + String delimiter, String prefix, String marker, Integer maxresults, List include, + Integer timeout, String startFrom, String endBefore, String requestId, Context context) { + try { + final String restype = "container"; + final String comp = "list"; + final String accept = "application/vnd.apache.arrow.stream"; + String includeConverted = (include == null) + ? null + : include.stream() + .map(paramItemValue -> Objects.toString(paramItemValue, "")) + .collect(Collectors.joining(",")); + return service.listBlobHierarchySegmentApacheArrowNoCustomHeadersSync(this.client.getUrl(), containerName, + restype, comp, accept, prefix, delimiter, marker, maxresults, includeConverted, timeout, startFrom, + endBefore, this.client.getVersion(), requestId, context); } catch (BlobStorageExceptionInternal internalException) { throw ModelHelper.mapToBlobStorageException(internalException); } diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/models/BlobItemInternal.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/models/BlobItemInternal.java index ff98bcc2dbc5..b4206292da11 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/models/BlobItemInternal.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/models/BlobItemInternal.java @@ -80,6 +80,12 @@ public final class BlobItemInternal implements XmlSerializable @Generated private Boolean hasVersionsOnly; + /* + * When a blob is encrypted with a customer provided key and has application metadata, + * the Encrypted field will be set to true and the metadata will be null. + */ + private Boolean metadataEncrypted; + /* * The IsPrefix property. */ @@ -335,6 +341,27 @@ public BlobItemInternal setIsPrefix(Boolean isPrefix) { return this; } + /** + * Get the metadataEncrypted property: When a blob is encrypted with a customer provided key and has application + * metadata, the Encrypted field will be set to true and the metadata will be null. + * + * @return the metadataEncrypted value. + */ + public Boolean isMetadataEncrypted() { + return this.metadataEncrypted; + } + + /** + * Set the metadataEncrypted property. + * + * @param metadataEncrypted the metadataEncrypted value to set. + * @return the BlobItemInternal object itself. + */ + public BlobItemInternal setMetadataEncrypted(Boolean metadataEncrypted) { + this.metadataEncrypted = metadataEncrypted; + return this; + } + @Generated @Override public XmlWriter toXml(XmlWriter xmlWriter) throws XMLStreamException { diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/models/BlobItemPropertiesInternal.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/models/BlobItemPropertiesInternal.java index 909005607d59..7dc441380236 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/models/BlobItemPropertiesInternal.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/models/BlobItemPropertiesInternal.java @@ -272,6 +272,21 @@ public final class BlobItemPropertiesInternal implements XmlSerializable blobItems; + private final String nextMarker; + private final Integer numberOfRecords; + + /** + * Creates an ArrowListBlobsResult. + * + * @param blobItems the deserialized blob items + * @param nextMarker the continuation token for the next page, or null if this is the last page + * @param numberOfRecords the total number of records reported by the service, or null if not present + */ + public ArrowListBlobsResult(List blobItems, String nextMarker, Integer numberOfRecords) { + this.blobItems = blobItems; + this.nextMarker = nextMarker; + this.numberOfRecords = numberOfRecords; + } + + /** + * @return the deserialized blob items + */ + public List getBlobItems() { + return blobItems; + } + + /** + * @return the continuation token for the next page, or null if this is the last page + */ + public String getNextMarker() { + return nextMarker; + } + + /** + * @return the total number of records reported by the service, or null if not present + */ + public Integer getNumberOfRecords() { + return numberOfRecords; + } + } + + private ArrowBlobListDeserializer() { + } + + /** + * Deserializes an Arrow IPC stream into blob items and pagination metadata. + * + * @param arrowStream the Arrow IPC input stream from the service response + * @return the deserialized result containing blob items and next marker + * @throws RuntimeException if deserialization fails + */ + public static ArrowListBlobsResult deserialize(InputStream arrowStream) { + List results = new ArrayList<>(); + String nextMarker = null; + Integer numberOfRecords = null; + + try (BufferAllocator allocator = new RootAllocator(); + ArrowStreamReader reader = new ArrowStreamReader(arrowStream, allocator)) { + + VectorSchemaRoot root = reader.getVectorSchemaRoot(); + + // Extract pagination metadata from schema + Map schemaMetadata = root.getSchema().getCustomMetadata(); + if (schemaMetadata != null) { + nextMarker = schemaMetadata.get("NextMarker"); + if (nextMarker != null && nextMarker.isEmpty()) { + nextMarker = null; + } + + String numberOfRecordsStr = schemaMetadata.get("NumberOfRecords"); + if (numberOfRecordsStr != null && !numberOfRecordsStr.isEmpty()) { + numberOfRecords = Integer.parseInt(numberOfRecordsStr); + } + } + + // Read all batches + while (reader.loadNextBatch()) { + int rowCount = root.getRowCount(); + for (int i = 0; i < rowCount; i++) { + results.add(readRow(root, i)); + } + } + } catch (IOException e) { + throw new RuntimeException("Failed to deserialize Arrow IPC response", e); + } + + return new ArrowListBlobsResult(results, nextMarker, numberOfRecords); + } + + private static BlobItemInternal readRow(VectorSchemaRoot root, int index) { + BlobItemInternal item = new BlobItemInternal(); + + // Name + String name = getVarChar(root, "Name", index); + if (name != null) { + item.setName(new BlobName().setContent(name)); + } + + // ResourceType — hierarchy listings use "blobprefix" for virtual directory rows + String resourceType = getVarChar(root, "ResourceType", index); + if ("blobprefix".equals(resourceType)) { + item.setIsPrefix(true); + return item; + } + + BlobItemPropertiesInternal properties = new BlobItemPropertiesInternal(); + + // Deleted + Boolean deleted = getBit(root, "Deleted", index); + if (deleted != null) { + item.setDeleted(deleted); + } + + // Snapshot + item.setSnapshot(getVarChar(root, "Snapshot", index)); + + // VersionId + item.setVersionId(getVarChar(root, "VersionId", index)); + + // IsCurrentVersion + item.setIsCurrentVersion(getBit(root, "IsCurrentVersion", index)); + + // HasVersionsOnly + item.setHasVersionsOnly(getBit(root, "HasVersionsOnly", index)); + + // Metadata + Map metadata = getMap(root, "Metadata", index); + if (metadata != null) { + item.setMetadata(metadata); + } + + // OrMetadata + Map orMetadata = getMap(root, "OrMetadata", index); + if (orMetadata != null) { + item.setObjectReplicationMetadata(orMetadata); + } + + // Tags + Map tags = getMap(root, "Tags", index); + if (tags != null) { + item.setBlobTags(ModelHelper.toBlobTags(tags)); + } + + // Encrypted — indicates metadata is encrypted with customer-provided key + item.setMetadataEncrypted(getBit(root, "Encrypted", index)); + + // --- Properties --- + + properties.setCreationTime(getTimestamp(root, "Creation-Time", index)); + properties.setLastModified(getTimestamp(root, "Last-Modified", index)); + properties.setETag(getVarChar(root, "Etag", index)); + properties.setContentLength(getUInt64(root, "Content-Length", index)); + properties.setContentType(getVarChar(root, "Content-Type", index)); + properties.setContentEncoding(getVarChar(root, "Content-Encoding", index)); + properties.setContentLanguage(getVarChar(root, "Content-Language", index)); + properties.setContentDisposition(getVarChar(root, "Content-Disposition", index)); + properties.setCacheControl(getVarChar(root, "Cache-Control", index)); + + // Content-MD5: service returns Base64 string, property expects byte[] + String contentMd5 = getVarChar(root, "Content-MD5", index); + if (contentMd5 != null) { + properties.setContentMd5(Base64.getDecoder().decode(contentMd5)); + } + + // Content-CRC64: same encoding as Content-MD5 + String contentCrc64 = getVarChar(root, "Content-CRC64", index); + if (contentCrc64 != null) { + properties.setContentCrc64(Base64.getDecoder().decode(contentCrc64)); + } + + // BlobType + String blobType = getVarChar(root, "BlobType", index); + if (blobType != null) { + properties.setBlobType(BlobType.fromString(blobType)); + } + + // AccessTier + String accessTier = getVarChar(root, "AccessTier", index); + if (accessTier != null) { + properties.setAccessTier(AccessTier.fromString(accessTier)); + } + properties.setAccessTierInferred(getBit(root, "AccessTierInferred", index)); + properties.setAccessTierChangeTime(getTimestamp(root, "AccessTierChangeTime", index)); + + // SmartAccessTier + String smartAccessTier = getVarChar(root, "SmartAccessTier", index); + if (smartAccessTier != null) { + properties.setSmartAccessTier(AccessTier.fromString(smartAccessTier)); + } + + // Lease + String leaseStatus = getVarChar(root, "LeaseStatus", index); + if (leaseStatus != null) { + properties.setLeaseStatus(LeaseStatusType.fromString(leaseStatus)); + } + String leaseState = getVarChar(root, "LeaseState", index); + if (leaseState != null) { + properties.setLeaseState(LeaseStateType.fromString(leaseState)); + } + String leaseDuration = getVarChar(root, "LeaseDuration", index); + if (leaseDuration != null) { + properties.setLeaseDuration(LeaseDurationType.fromString(leaseDuration)); + } + + // Encryption + properties.setServerEncrypted(getBit(root, "ServerEncrypted", index)); + properties.setCustomerProvidedKeySha256(getVarChar(root, "CustomerProvidedKeySha256", index)); + properties.setEncryptionScope(getVarChar(root, "EncryptionScope", index)); + properties.setIncrementalCopy(getBit(root, "IncrementalCopy", index)); + + // OrsPolicySourceBlob + properties.setOrsPolicySourceBlob(getVarChar(root, "OrsPolicySourceBlob", index)); + + // AffinityId + properties.setAffinityId(getVarChar(root, "AffinityId", index)); + + // Copy fields + properties.setCopyId(getVarChar(root, "CopyId", index)); + String copyStatus = getVarChar(root, "CopyStatus", index); + if (copyStatus != null) { + properties.setCopyStatus(CopyStatusType.fromString(copyStatus)); + } + properties.setCopySource(getVarChar(root, "CopySource", index)); + properties.setCopyProgress(getVarChar(root, "CopyProgress", index)); + properties.setCopyCompletionTime(getTimestamp(root, "CopyCompletionTime", index)); + properties.setCopyStatusDescription(getVarChar(root, "CopyStatusDescription", index)); + properties.setDestinationSnapshot(getVarChar(root, "CopyDestinationSnapshot", index)); + + // Sequence number + properties.setBlobSequenceNumber(getUInt64(root, "x-ms-blob-sequence-number", index)); + + // Misc properties + properties.setIsSealed(getBit(root, "Sealed", index)); + properties.setLegalHold(getBit(root, "LegalHold", index)); + properties.setDeletedTime(getTimestamp(root, "DeletedTime", index)); + properties.setLastAccessedOn(getTimestamp(root, "LastAccessTime", index)); + properties.setImmutabilityPolicyExpiresOn(getTimestamp(root, "ImmutabilityPolicyUntilDate", index)); + + String immutabilityMode = getVarChar(root, "ImmutabilityPolicyMode", index); + if (immutabilityMode != null) { + properties.setImmutabilityPolicyMode(BlobImmutabilityPolicyMode.fromString(immutabilityMode)); + } + + String archiveStatus = getVarChar(root, "ArchiveStatus", index); + if (archiveStatus != null) { + properties.setArchiveStatus(ArchiveStatus.fromString(archiveStatus)); + } + + String rehydratePriority = getVarChar(root, "RehydratePriority", index); + if (rehydratePriority != null) { + properties.setRehydratePriority(RehydratePriority.fromString(rehydratePriority)); + } + + // TagCount and RemainingRetentionDays — service uses uint64 but property is Integer + Long tagCount = getUInt64(root, "TagCount", index); + if (tagCount != null) { + properties.setTagCount(tagCount.intValue()); + } + Long remainingRetentionDays = getUInt64(root, "RemainingRetentionDays", index); + if (remainingRetentionDays != null) { + properties.setRemainingRetentionDays(remainingRetentionDays.intValue()); + } + + item.setProperties(properties); + return item; + } + + // --- Safe vector read helpers --- + // Each returns null if the column is absent from the schema or the value is null at the given row. + + private static String getVarChar(VectorSchemaRoot root, String name, int index) { + FieldVector vec = root.getVector(name); + if (vec == null || vec.isNull(index)) { + return null; + } + return new String(((VarCharVector) vec).get(index), StandardCharsets.UTF_8); + } + + private static Long getUInt64(VectorSchemaRoot root, String name, int index) { + FieldVector vec = root.getVector(name); + if (vec == null || vec.isNull(index)) { + return null; + } + // Arrow may represent uint64 as BigIntVector (signed 64-bit) or UInt8Vector + if (vec instanceof BigIntVector) { + return ((BigIntVector) vec).get(index); + } else if (vec instanceof UInt8Vector) { + return ((UInt8Vector) vec).get(index); + } + return null; + } + + private static Boolean getBit(VectorSchemaRoot root, String name, int index) { + FieldVector vec = root.getVector(name); + if (vec == null || vec.isNull(index)) { + return null; + } + return ((BitVector) vec).get(index) == 1; + } + + private static OffsetDateTime getTimestamp(VectorSchemaRoot root, String name, int index) { + FieldVector vec = root.getVector(name); + if (vec == null || vec.isNull(index)) { + return null; + } + // Service returns Timestamp(SECOND, null) — epoch seconds without timezone, treat as UTC + if (vec instanceof TimeStampSecVector) { + long epochSeconds = ((TimeStampSecVector) vec).get(index); + return OffsetDateTime.ofInstant(Instant.ofEpochSecond(epochSeconds), ZoneOffset.UTC); + } + return null; + } + + private static Map getMap(VectorSchemaRoot root, String name, int index) { + FieldVector vec = root.getVector(name); + if (vec == null || vec.isNull(index)) { + return null; + } + if (vec instanceof MapVector) { + MapVector mapVec = (MapVector) vec; + UnionMapReader reader = mapVec.getReader(); + reader.setPosition(index); + Map map = new HashMap<>(); + while (reader.next()) { + String key = reader.key().readText().toString(); + String value = reader.value().readText().toString(); + map.put(key, value); + } + return map.isEmpty() ? null : map; + } + return null; + } +} diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/util/ModelHelper.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/util/ModelHelper.java index cb859dfa595d..6bd5deb8cc55 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/util/ModelHelper.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/util/ModelHelper.java @@ -47,6 +47,7 @@ import com.azure.storage.blob.models.PageBlobCopyIncrementalRequestConditions; import com.azure.storage.blob.models.PageRange; import com.azure.storage.blob.models.ParallelTransferOptions; +import com.azure.storage.blob.models.StorageResponseSerializationFormat; import com.azure.storage.blob.models.TaggedBlobItem; import com.azure.storage.common.Utility; import com.azure.storage.common.implementation.Constants; @@ -85,6 +86,14 @@ public final class ModelHelper { */ public static final int PAGE_BYTES = 512; + /** + * The format that {@link StorageResponseSerializationFormat#AUTO} currently resolves to on the + * wire. Changing this constant is a behavioral change (and should be noted in the CHANGELOG) + * but it is not a public API change. + */ + private static final StorageResponseSerializationFormat DEFAULT_SERIALIZATION_FORMAT + = StorageResponseSerializationFormat.XML; + /** * Determines whether the passed authority is IP style, that is, it is of the format {@code :}. * @@ -663,6 +672,22 @@ public static BlobStorageException mapToBlobStorageException(BlobStorageExceptio internal.getResponse(), code, headerName), internal.getResponse(), internal.getValue()); } + /** + * Resolves a user-supplied {@link StorageResponseSerializationFormat} to the concrete value + * to send on the wire. Treats {@code null} and {@link StorageResponseSerializationFormat#AUTO} + * identically — both yield {@link #DEFAULT_SERIALIZATION_FORMAT}. + * + * @param format the format requested by the caller, or {@code null} if unset. + * @return the concrete {@link StorageResponseSerializationFormat} to send on the wire. + */ + public static StorageResponseSerializationFormat + resolveSerializationFormat(StorageResponseSerializationFormat format) { + if (format == null || format == StorageResponseSerializationFormat.AUTO) { + return DEFAULT_SERIALIZATION_FORMAT; + } + return format; + } + private ModelHelper() { } } diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/BlobItem.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/BlobItem.java index 7b3558005a5e..049762502c29 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/BlobItem.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/BlobItem.java @@ -274,6 +274,16 @@ public BlobItem setHasVersionsOnly(Boolean hasVersionsOnly) { return this; } + /** + * Get the metadataEncrypted property: When a blob is encrypted with a customer provided key and has application + * metadata, the Encrypted field will be set to true and the metadata will be null. + * + * @return the metadataEncrypted value. + */ + public Boolean isMetadataEncrypted() { + return blobItemInternal.isMetadataEncrypted(); + } + /** * Get the isPrefix property: If blobs are named to mimic a directory hierarchy (i.e. path elements separated by a * delimiter), this property may be used to determine if the {@code BlobItem} is a virtual directory. diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/BlobItemProperties.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/BlobItemProperties.java index ccd3b89a3f5b..9f0dc5c3b3f9 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/BlobItemProperties.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/BlobItemProperties.java @@ -845,6 +845,33 @@ public BlobItemProperties setImmutabilityPolicy(BlobImmutabilityPolicy immutabil return this; } + /** + * Get the contentCrc64 property: The Content-CRC64 property. + * + * @return the contentCrc64 value. + */ + public byte[] getContentCrc64() { + return internalProperties.getContentCrc64(); + } + + /** + * Get the orsPolicySourceBlob property: The OrsPolicySourceBlob property. + * + * @return the orsPolicySourceBlob value. + */ + public String getOrsPolicySourceBlob() { + return internalProperties.getOrsPolicySourceBlob(); + } + + /** + * Get the affinityId property: The AffinityId property. + * + * @return the affinityId value. + */ + public String getAffinityId() { + return internalProperties.getAffinityId(); + } + /** * Get the hasLegalHold property: The LegalHold property. * diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/BlobRetentionPolicy.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/BlobRetentionPolicy.java index 6b4042dbc0d9..c0af296985d4 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/BlobRetentionPolicy.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/BlobRetentionPolicy.java @@ -17,7 +17,7 @@ * the retention policy which determines how long the associated data should persist. */ @Fluent -public final class BlobRetentionPolicy implements XmlSerializable { +public class BlobRetentionPolicy implements XmlSerializable { /* * Indicates whether a retention policy is enabled for the storage service */ @@ -40,7 +40,7 @@ public BlobRetentionPolicy() { /** * Get the enabled property: Indicates whether a retention policy is enabled for the storage service. - * + * * @return the enabled value. */ @Generated @@ -50,7 +50,7 @@ public boolean isEnabled() { /** * Set the enabled property: Indicates whether a retention policy is enabled for the storage service. - * + * * @param enabled the enabled value to set. * @return the BlobRetentionPolicy object itself. */ @@ -63,7 +63,7 @@ public BlobRetentionPolicy setEnabled(boolean enabled) { /** * Get the days property: 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. - * + * * @return the days value. */ @Generated @@ -74,7 +74,7 @@ public Integer getDays() { /** * Set the days property: 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. - * + * * @param days the days value to set. * @return the BlobRetentionPolicy object itself. */ @@ -103,7 +103,7 @@ public XmlWriter toXml(XmlWriter xmlWriter, String rootElementName) throws XMLSt /** * Reads an instance of BlobRetentionPolicy from the XmlReader. - * + * * @param xmlReader The XmlReader being read. * @return An instance of BlobRetentionPolicy if the XmlReader was pointing to an instance of it, or null if it was * pointing to XML null. @@ -116,7 +116,7 @@ public static BlobRetentionPolicy fromXml(XmlReader xmlReader) throws XMLStreamE /** * Reads an instance of BlobRetentionPolicy from the XmlReader. - * + * * @param xmlReader The XmlReader being read. * @param rootElementName Optional root element name to override the default defined by the model. Used to support * cases where the model can deserialize from different root element names. diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/ListBlobsOptions.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/ListBlobsOptions.java index 47f29c2ab2b3..e434681ac6e9 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/ListBlobsOptions.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/ListBlobsOptions.java @@ -19,6 +19,8 @@ public final class ListBlobsOptions { private String prefix; private String startFrom; private Integer maxResultsPerPage; + private StorageResponseSerializationFormat storageResponseSerializationFormat; + private String endBefore; /** * Constructs an unpopulated {@link ListBlobsOptions}. @@ -74,7 +76,7 @@ public ListBlobsOptions setPrefix(String prefix) { * This parameter is similar to the prefix filter: it allows listing blobs starting from the specified path, rather than from the beginning of the container. * For non-recursive lists, only one entity level is supported. * - * @return the marker indicating where to start listing blobs + * @return the marker indicating where to start listing blobs (inclusive) */ public String getStartFrom() { return startFrom; @@ -84,7 +86,7 @@ public String getStartFrom() { * Sets an optional parameter that specifies an absolute path within the container. This parameter is similar to the prefix filter: it allows listing blobs starting from the specified path, rather than from the beginning of the container. * For non-recursive lists, only one entity level is supported. * - * @param startFrom The marker indicating where to start listing blobs + * @param startFrom The marker indicating where to start listing blobs (inclusive) * @return the updated ListBlobsOptions object */ public ListBlobsOptions setStartFrom(String startFrom) { @@ -92,6 +94,49 @@ public ListBlobsOptions setStartFrom(String startFrom) { return this; } + /** + * Gets the endBefore value. Only supported with Arrow listings. The listing will end before this path (exclusive). + * + * @return the endBefore value. + */ + public String getEndBefore() { + return endBefore; + } + + /** + * Sets the endBefore value. Only supported with Arrow listings. The listing will end before this path (exclusive). + * + * @param endBefore the endBefore value to set. + * @return the updated ListBlobsOptions object. + */ + public ListBlobsOptions setEndBefore(String endBefore) { + this.endBefore = endBefore; + return this; + } + + /** + * Gets the response serialization format the service should use when listing blobs. + * + * @return the {@link StorageResponseSerializationFormat}, or {@code null} if unset + * (equivalent to {@link StorageResponseSerializationFormat#AUTO}). + */ + public StorageResponseSerializationFormat getStorageResponseSerializationFormat() { + return storageResponseSerializationFormat; + } + + /** + * Sets the response serialization format the service should use when listing blobs. + * + * @param storageResponseSerializationFormat the format to request. {@code null} and + * {@link StorageResponseSerializationFormat#AUTO} both let the SDK pick. + * @return the updated {@link ListBlobsOptions} object. + */ + public ListBlobsOptions + setStorageResponseSerializationFormat(StorageResponseSerializationFormat storageResponseSerializationFormat) { + this.storageResponseSerializationFormat = storageResponseSerializationFormat; + return this; + } + /** * Specifies the maximum number of blobs to return, including all BlobPrefix elements. If the request does not * specify maxResultsPerPage or specifies a value greater than 5,000, the server will return up to 5,000 items. diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/StorageResponseSerializationFormat.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/StorageResponseSerializationFormat.java new file mode 100644 index 000000000000..e5017accedbc --- /dev/null +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/models/StorageResponseSerializationFormat.java @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.storage.blob.models; + +/** + * Defines the serialization format the service uses for list-blobs responses. + */ +public enum StorageResponseSerializationFormat { + /** + * Let the SDK choose the serialization format that is most appropriate for the request. + *

+ * The exact format selected by {@code AUTO} is an implementation detail and may change + * between SDK releases. Choose {@link #XML} or {@link #ARROW} explicitly if you require + * a specific format. + */ + AUTO, + + /** + * XML response format. + */ + XML, + + /** + * Apache Arrow response format. + */ + ARROW +} diff --git a/sdk/storage/azure-storage-blob/src/main/java/module-info.java b/sdk/storage/azure-storage-blob/src/main/java/module-info.java index 597a417add7f..e622d0aa2e95 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/module-info.java +++ b/sdk/storage/azure-storage-blob/src/main/java/module-info.java @@ -5,6 +5,9 @@ requires transitive com.azure.storage.common; requires com.azure.storage.internal.avro; + requires org.apache.arrow.vector; + requires org.apache.arrow.memory.core; + requires org.apache.arrow.format; exports com.azure.storage.blob; exports com.azure.storage.blob.models; diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerApiTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerApiTests.java index f46116acdbb5..d4c9d3838d35 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerApiTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerApiTests.java @@ -34,6 +34,7 @@ import com.azure.storage.blob.models.PublicAccessType; import com.azure.storage.blob.models.RehydratePriority; import com.azure.storage.blob.models.StorageAccountInfo; +import com.azure.storage.blob.models.StorageResponseSerializationFormat; import com.azure.storage.blob.models.TaggedBlobItem; import com.azure.storage.blob.options.BlobContainerCreateOptions; import com.azure.storage.blob.options.BlobParallelUploadOptions; @@ -50,6 +51,10 @@ import com.azure.storage.common.test.shared.extensions.PlaybackOnly; import com.azure.storage.common.test.shared.extensions.RequiredServiceVersion; import com.azure.storage.common.test.shared.policy.InvalidServiceVersionPipelinePolicy; +import org.apache.arrow.memory.BufferAllocator; +import org.apache.arrow.memory.RootAllocator; +import org.apache.arrow.vector.ipc.ArrowStreamReader; +import org.apache.arrow.vector.VectorSchemaRoot; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -58,7 +63,19 @@ import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.ValueSource; +import com.azure.core.http.HttpPipeline; +import com.azure.storage.blob.implementation.AzureBlobStorageImpl; +import com.azure.storage.blob.implementation.AzureBlobStorageImplBuilder; +import com.azure.storage.blob.implementation.models.ContainersListBlobFlatSegmentApacheArrowHeaders; +import com.azure.storage.blob.implementation.models.ContainersListBlobHierarchySegmentApacheArrowHeaders; +import com.azure.storage.blob.implementation.util.ArrowBlobListDeserializer; +import com.azure.storage.blob.implementation.util.ModelHelper; +import com.azure.storage.blob.models.ListBlobsIncludeItem; +import com.azure.core.http.rest.ResponseBase; + import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.util.ArrayList; import java.net.URL; import java.time.OffsetDateTime; import java.util.Arrays; @@ -2128,4 +2145,313 @@ public void getBlobContainerUrlEncodesContainerName() { // then: // assertThrows(BlobStorageException.class, () -> // } + + @Test + @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2026-06-06") + public void listBlobsArrowBasic() { + // Upload a test blob + String blobName = generateBlobName(); + cc.getBlobClient(blobName).getBlockBlobClient().upload(DATA.getDefaultInputStream(), DATA.getDefaultDataSize()); + + ListBlobsOptions options + = new ListBlobsOptions().setStorageResponseSerializationFormat(StorageResponseSerializationFormat.ARROW); + List blobs = cc.listBlobs(options, null).stream().collect(Collectors.toList()); + + assertEquals(1, blobs.size()); + assertEquals(blobName, blobs.get(0).getName()); + assertNotNull(blobs.get(0).getProperties()); + assertEquals(DATA.getDefaultDataSize(), blobs.get(0).getProperties().getContentLength()); + assertEquals(BlobType.BLOCK_BLOB, blobs.get(0).getProperties().getBlobType()); + assertNotNull(blobs.get(0).getProperties().getLastModified()); + assertNotNull(blobs.get(0).getProperties().getETag()); + } + + @Test + @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2026-06-06") + public void listBlobsArrowWithTags() { + // Upload a blob and set tags + String blobName = generateBlobName(); + cc.getBlobClient(blobName).getBlockBlobClient().upload(DATA.getDefaultInputStream(), DATA.getDefaultDataSize()); + + Map tags = new HashMap<>(); + tags.put("tagkey", "tagvalue"); + cc.getBlobClient(blobName).setTags(tags); + + // List with Arrow + retrieveTags + ListBlobsOptions options + = new ListBlobsOptions().setStorageResponseSerializationFormat(StorageResponseSerializationFormat.ARROW) + .setDetails(new BlobListDetails().setRetrieveTags(true)); + List blobs = cc.listBlobs(options, null).stream().collect(Collectors.toList()); + + assertEquals(1, blobs.size()); + assertEquals(blobName, blobs.get(0).getName()); + assertNotNull(blobs.get(0).getTags()); + assertEquals("tagvalue", blobs.get(0).getTags().get("tagkey")); + } + + @ParameterizedTest + @MethodSource("listBlobsFlatRehydratePrioritySupplier") + @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2026-06-06") + public void listBlobsArrowRehydratePriority(RehydratePriority rehydratePriority) { + String name = generateBlobName(); + BlockBlobClient bc = cc.getBlobClient(name).getBlockBlobClient(); + + bc.upload(DATA.getDefaultInputStream(), 7); + + if (rehydratePriority != null) { + bc.setAccessTier(AccessTier.ARCHIVE); + bc.setAccessTierWithResponse(new BlobSetAccessTierOptions(AccessTier.HOT).setPriority(rehydratePriority), + null, null); + } + + ListBlobsOptions options + = new ListBlobsOptions().setStorageResponseSerializationFormat(StorageResponseSerializationFormat.ARROW); + BlobItem item = cc.listBlobs(options, null).iterator().next(); + + assertEquals(rehydratePriority, item.getProperties().getRehydratePriority()); + } + + @Test + @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2026-06-06") + public void listBlobsArrowWithMetadata() { + String blobName = generateBlobName(); + Map metadata = new HashMap<>(); + metadata.put("testkey", "testvalue"); + cc.getBlobClient(blobName) + .getBlockBlobClient() + .uploadWithResponse(DATA.getDefaultInputStream(), DATA.getDefaultDataSize(), null, metadata, null, null, + null, null, null); + + ListBlobsOptions options + = new ListBlobsOptions().setStorageResponseSerializationFormat(StorageResponseSerializationFormat.ARROW) + .setDetails(new BlobListDetails().setRetrieveMetadata(true)); + List blobs = cc.listBlobs(options, null).stream().collect(Collectors.toList()); + + assertEquals(1, blobs.size()); + assertNotNull(blobs.get(0).getMetadata()); + assertEquals("testvalue", blobs.get(0).getMetadata().get("testkey")); + } + + @Test + @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2026-06-06") + public void listBlobsArrowPagination() { + // Upload 3 blobs + for (int i = 0; i < 4; i++) { + cc.getBlobClient("blob" + i) + .getBlockBlobClient() + .upload(DATA.getDefaultInputStream(), DATA.getDefaultDataSize()); + } + + ListBlobsOptions options + = new ListBlobsOptions().setStorageResponseSerializationFormat(StorageResponseSerializationFormat.ARROW) + .setMaxResultsPerPage(1); + List allBlobs = new ArrayList<>(); + for (PagedResponse page : cc.listBlobs(options, null).iterableByPage()) { + assertTrue(page.getValue().size() <= 1); + allBlobs.addAll(page.getValue()); + } + + cc.listBlobs().iterableByPage(2).forEach(page -> { + assertEquals(2, page.getValue().size()); + }); + + assertEquals(4, allBlobs.size()); + } + + @Test + @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2026-06-06") + public void listBlobsArrowNullUseArrowUsesXml() { + // Default apacheArrowEnabled is null — should use XML path without error + String blobName = generateBlobName(); + cc.getBlobClient(blobName).getBlockBlobClient().upload(DATA.getDefaultInputStream(), DATA.getDefaultDataSize()); + + ListBlobsOptions options = new ListBlobsOptions(); + assertNull(options.getStorageResponseSerializationFormat()); + + List blobs = cc.listBlobs(options, null).stream().collect(Collectors.toList()); + assertEquals(1, blobs.size()); + assertEquals(blobName, blobs.get(0).getName()); + } + + @LiveOnly + @Test + @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2026-06-06") + public void listBlobsArrowEncryptedBlob() { + // Upload a blob with CPK (customer-provided key) + String blobName = generateBlobName(); + CustomerProvidedKey cpk = new CustomerProvidedKey(Base64.getEncoder().encodeToString(getRandomKey())); + BlobClient cpkClient = cc.getBlobClient(blobName).getCustomerProvidedKeyClient(cpk); + cpkClient.getBlockBlobClient().upload(DATA.getDefaultInputStream(), DATA.getDefaultDataSize()); + + ListBlobsOptions options + = new ListBlobsOptions().setStorageResponseSerializationFormat(StorageResponseSerializationFormat.ARROW); + List blobs = cc.listBlobs(options, null).stream().collect(Collectors.toList()); + + assertEquals(1, blobs.size()); + assertEquals(blobName, blobs.get(0).getName()); + // CPK blob should have server-encrypted = true + assertTrue(blobs.get(0).getProperties().isServerEncrypted()); + // Metadata should be null (no metadata was set) + assertNull(blobs.get(0).getMetadata()); + } + + @Test + @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2026-06-06") + public void listBlobsArrowDeserializer() throws Exception { + String blobName = generateBlobName(); + Map metadata = new HashMap<>(); + metadata.put("testkey", "testvalue"); + cc.getBlobClient(blobName) + .getBlockBlobClient() + .uploadWithResponse(DATA.getDefaultInputStream(), 7, null, metadata, null, null, null, null, null); + + AzureBlobStorageImpl impl = new AzureBlobStorageImplBuilder().pipeline(cc.getHttpPipeline()) + .url(cc.getAccountUrl()) + .version(BlobServiceVersion.V2026_06_06.getVersion()) + .buildClient(); + + // Call the Arrow endpoint + ArrayList include = new ArrayList<>(); + include.add(ListBlobsIncludeItem.METADATA); + + ResponseBase response = impl.getContainers() + .listBlobFlatSegmentApacheArrowWithResponse(containerName, null, null, null, include, null, null, null, + null, com.azure.core.util.Context.NONE); + + // Verify Content-Type is Arrow + String contentType = response.getDeserializedHeaders().getContentType(); + assertTrue(contentType.contains("application/vnd.apache.arrow.stream"), + "Expected Arrow content type but got: " + contentType); + + // Deserialize using ArrowBlobListDeserializer + ArrowBlobListDeserializer.ArrowListBlobsResult result + = ArrowBlobListDeserializer.deserialize(response.getValue()); + + // Verify pagination — single blob, no next page + assertNull(result.getNextMarker()); + + // Verify we got exactly one blob + assertEquals(1, result.getBlobItems().size()); + + com.azure.storage.blob.implementation.models.BlobItemInternal item = result.getBlobItems().get(0); + + // Name + assertNotNull(item.getName()); + assertEquals(blobName, item.getName().getContent()); + + // Properties + assertNotNull(item.getProperties()); + assertEquals(7L, (long) item.getProperties().getContentLength()); + assertEquals("application/octet-stream", item.getProperties().getContentType()); + assertNotNull(item.getProperties().getETag()); + assertNotNull(item.getProperties().getLastModified()); + assertNotNull(item.getProperties().getCreationTime()); + assertEquals(BlobType.BLOCK_BLOB, item.getProperties().getBlobType()); + assertEquals(AccessTier.HOT, item.getProperties().getAccessTier()); + assertTrue(item.getProperties().isAccessTierInferred()); + assertTrue(item.getProperties().isServerEncrypted()); + assertEquals(LeaseStateType.AVAILABLE, item.getProperties().getLeaseState()); + assertEquals(LeaseStatusType.UNLOCKED, item.getProperties().getLeaseStatus()); + assertNotNull(item.getProperties().getContentMd5()); + + // Metadata + assertNotNull(item.getMetadata()); + assertEquals("testvalue", item.getMetadata().get("testkey")); + + // Verify ModelHelper can convert to public BlobItem + BlobItem publicItem = ModelHelper.populateBlobItem(item); + assertEquals(blobName, publicItem.getName()); + assertEquals(7L, (long) publicItem.getProperties().getContentLength()); + } + + @Test + @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2026-06-06") + public void listBlobsByHierarchyArrowBasic() { + // Upload blobs in a directory structure + cc.getBlobClient("dir/blob1") + .getBlockBlobClient() + .upload(DATA.getDefaultInputStream(), DATA.getDefaultDataSize()); + cc.getBlobClient("dir/blob2") + .getBlockBlobClient() + .upload(DATA.getDefaultInputStream(), DATA.getDefaultDataSize()); + cc.getBlobClient("topblob") + .getBlockBlobClient() + .upload(DATA.getDefaultInputStream(), DATA.getDefaultDataSize()); + + ListBlobsOptions options + = new ListBlobsOptions().setStorageResponseSerializationFormat(StorageResponseSerializationFormat.ARROW); + List items = cc.listBlobsByHierarchy("/", options, null).stream().collect(Collectors.toList()); + + // Root level: one prefix "dir/" and one blob "topblob" + assertEquals(2, items.size()); + + BlobItem prefixItem = items.stream().filter(BlobItem::isPrefix).findFirst().orElse(null); + BlobItem blobItem = items.stream().filter(i -> !i.isPrefix()).findFirst().orElse(null); + + assertNotNull(prefixItem); + assertEquals("dir/", prefixItem.getName()); + assertTrue(prefixItem.isPrefix()); + + assertNotNull(blobItem); + assertEquals("topblob", blobItem.getName()); + assertFalse(blobItem.isPrefix()); + assertNotNull(blobItem.getProperties()); + assertEquals(DATA.getDefaultDataSize(), blobItem.getProperties().getContentLength()); + assertEquals(BlobType.BLOCK_BLOB, blobItem.getProperties().getBlobType()); + assertNotNull(blobItem.getProperties().getLastModified()); + assertNotNull(blobItem.getProperties().getETag()); + } + + @Test + @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2026-06-06") + public void listBlobsByHierarchyArrowWithMetadata() { + String blobName = generateBlobName(); + Map metadata = new HashMap<>(); + metadata.put("testkey", "testvalue"); + cc.getBlobClient("dir/" + blobName) + .getBlockBlobClient() + .uploadWithResponse(DATA.getDefaultInputStream(), DATA.getDefaultDataSize(), null, metadata, null, null, + null, null, null); + cc.getBlobClient("topblob") + .getBlockBlobClient() + .upload(DATA.getDefaultInputStream(), DATA.getDefaultDataSize()); + + ListBlobsOptions options + = new ListBlobsOptions().setStorageResponseSerializationFormat(StorageResponseSerializationFormat.ARROW) + .setPrefix("dir/") + .setDetails(new BlobListDetails().setRetrieveMetadata(true)); + List blobs = cc.listBlobsByHierarchy("/", options, null).stream().collect(Collectors.toList()); + + assertEquals(1, blobs.size()); + assertFalse(blobs.get(0).isPrefix()); + assertNotNull(blobs.get(0).getMetadata()); + assertEquals("testvalue", blobs.get(0).getMetadata().get("testkey")); + } + + @Test + @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2026-06-06") + public void listBlobsByHierarchyArrowPagination() { + // Upload blobs across multiple directories + for (int i = 0; i < 3; i++) { + cc.getBlobClient("dir" + i + "/blob") + .getBlockBlobClient() + .upload(DATA.getDefaultInputStream(), DATA.getDefaultDataSize()); + } + cc.getBlobClient("topblob") + .getBlockBlobClient() + .upload(DATA.getDefaultInputStream(), DATA.getDefaultDataSize()); + + ListBlobsOptions options + = new ListBlobsOptions().setStorageResponseSerializationFormat(StorageResponseSerializationFormat.ARROW) + .setMaxResultsPerPage(1); + List allItems = new ArrayList<>(); + for (PagedResponse page : cc.listBlobsByHierarchy("/", options, null).iterableByPage()) { + assertTrue(page.getValue().size() <= 1); + allItems.addAll(page.getValue()); + } + + // 3 prefixes + 1 blob = 4 items + assertEquals(4, allItems.size()); + } + } diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerAsyncApiTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerAsyncApiTests.java index 04ebc06dc2b6..ee240afdc4bc 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerAsyncApiTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerAsyncApiTests.java @@ -10,8 +10,14 @@ import com.azure.core.test.TestMode; import com.azure.core.test.utils.MockTokenCredential; import com.azure.core.util.Context; +import com.azure.core.util.FluxUtil; import com.azure.core.util.polling.PollerFlux; import com.azure.identity.DefaultAzureCredentialBuilder; +import com.azure.storage.blob.implementation.AzureBlobStorageImpl; +import com.azure.storage.blob.implementation.AzureBlobStorageImplBuilder; +import com.azure.storage.blob.implementation.models.BlobItemInternal; +import com.azure.storage.blob.implementation.util.ArrowBlobListDeserializer; +import com.azure.storage.blob.implementation.util.ModelHelper; import com.azure.storage.blob.models.*; import com.azure.storage.blob.options.BlobContainerCreateOptions; import com.azure.storage.blob.options.BlobParallelUploadOptions; @@ -41,6 +47,7 @@ import reactor.util.function.Tuple2; import java.net.URL; +import java.io.ByteArrayInputStream; import java.time.Duration; import java.time.OffsetDateTime; import java.util.*; @@ -2142,4 +2149,334 @@ public void getBlobContainerUrlEncodesContainerName() { assertTrue(containerClient.getBlobContainerUrl().contains("my%20container")); } + + @Test + @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2026-06-06") + public void listBlobsArrowBasic() { + // Upload a test blob + String blobName = generateBlobName(); + BlockBlobAsyncClient bc = ccAsync.getBlobAsyncClient(blobName).getBlockBlobAsyncClient(); + + ListBlobsOptions options + = new ListBlobsOptions().setStorageResponseSerializationFormat(StorageResponseSerializationFormat.ARROW); + + StepVerifier + .create( + bc.upload(DATA.getDefaultFlux(), DATA.getDefaultDataSize()).thenMany(ccAsync.listBlobs(options, null))) + .assertNext(item -> { + assertEquals(blobName, item.getName()); + assertNotNull(item.getProperties()); + assertEquals(DATA.getDefaultDataSize(), item.getProperties().getContentLength()); + assertEquals(BlobType.BLOCK_BLOB, item.getProperties().getBlobType()); + assertNotNull(item.getProperties().getLastModified()); + assertNotNull(item.getProperties().getETag()); + }) + .verifyComplete(); + } + + @Test + @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2026-06-06") + public void listBlobsArrowWithMetadata() { + String blobName = generateBlobName(); + Map metadata = new HashMap<>(); + metadata.put("testkey", "testvalue"); + BlockBlobAsyncClient bc = ccAsync.getBlobAsyncClient(blobName).getBlockBlobAsyncClient(); + + ListBlobsOptions options + = new ListBlobsOptions().setStorageResponseSerializationFormat(StorageResponseSerializationFormat.ARROW) + .setDetails(new BlobListDetails().setRetrieveMetadata(true)); + + StepVerifier.create( + bc.uploadWithResponse(DATA.getDefaultFlux(), DATA.getDefaultDataSize(), null, metadata, null, null, null) + .thenMany(ccAsync.listBlobs(options, null))) + .assertNext(item -> { + assertNotNull(item.getMetadata()); + assertEquals("testvalue", item.getMetadata().get("testkey")); + }) + .verifyComplete(); + } + + @Test + @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2026-06-06") + public void listBlobsArrowPagination() { + // Upload 4 blobs + Flux uploads = Flux.range(0, 4) + .flatMap(i -> ccAsync.getBlobAsyncClient("blob" + i) + .getBlockBlobAsyncClient() + .upload(DATA.getDefaultFlux(), DATA.getDefaultDataSize())); + + ListBlobsOptions options + = new ListBlobsOptions().setStorageResponseSerializationFormat(StorageResponseSerializationFormat.ARROW) + .setMaxResultsPerPage(1); + + Mono> result = uploads.then(ccAsync.listBlobs(options, null).byPage().doOnNext(page -> { + assertTrue(page.getValue().size() <= 1); + }).flatMap(page -> Flux.fromIterable(page.getValue())).collectList()); + + StepVerifier.create(result).assertNext(allBlobs -> assertEquals(4, allBlobs.size())).verifyComplete(); + + // Mirror the sync test's secondary assertion: requesting page size 2 yields exactly 2 blobs per page. + StepVerifier.create(ccAsync.listBlobs().byPage(2)).thenConsumeWhile(page -> { + assertEquals(2, page.getValue().size()); + return true; + }).verifyComplete(); + } + + @Test + @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2026-06-06") + public void listBlobsArrowNullUseArrowUsesXml() { + // Default apacheArrowEnabled is null — should use XML path without error + String blobName = generateBlobName(); + BlockBlobAsyncClient bc = ccAsync.getBlobAsyncClient(blobName).getBlockBlobAsyncClient(); + + ListBlobsOptions options = new ListBlobsOptions(); + assertNull(options.getStorageResponseSerializationFormat()); + + StepVerifier + .create( + bc.upload(DATA.getDefaultFlux(), DATA.getDefaultDataSize()).thenMany(ccAsync.listBlobs(options, null))) + .assertNext(item -> assertEquals(blobName, item.getName())) + .verifyComplete(); + } + + @LiveOnly + @Test + @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2026-06-06") + public void listBlobsArrowEncryptedBlob() { + // Upload a blob with CPK (customer-provided key) + String blobName = generateBlobName(); + CustomerProvidedKey cpk = new CustomerProvidedKey(Base64.getEncoder().encodeToString(getRandomKey())); + BlockBlobAsyncClient cpkClient + = ccAsync.getBlobAsyncClient(blobName).getCustomerProvidedKeyAsyncClient(cpk).getBlockBlobAsyncClient(); + + ListBlobsOptions options + = new ListBlobsOptions().setStorageResponseSerializationFormat(StorageResponseSerializationFormat.ARROW); + + StepVerifier.create(cpkClient.upload(DATA.getDefaultFlux(), DATA.getDefaultDataSize()) + .thenMany(ccAsync.listBlobs(options, null))).assertNext(item -> { + assertEquals(blobName, item.getName()); + // CPK blob should have server-encrypted = true + assertTrue(item.getProperties().isServerEncrypted()); + // Metadata should be null (no metadata was set) + assertNull(item.getMetadata()); + }).verifyComplete(); + } + + @ParameterizedTest + @MethodSource("listBlobsFlatRehydratePrioritySupplier") + @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2026-06-06") + public void listBlobsArrowRehydratePriority(RehydratePriority rehydratePriority) { + String name = generateBlobName(); + BlockBlobAsyncClient bc = ccAsync.getBlobAsyncClient(name).getBlockBlobAsyncClient(); + + Mono> rehydrate = Mono.empty(); + + if (rehydratePriority != null) { + rehydrate = bc.setAccessTier(AccessTier.ARCHIVE) + .then(bc.setAccessTierWithResponse( + new BlobSetAccessTierOptions(AccessTier.HOT).setPriority(rehydratePriority))); + } + + ListBlobsOptions options + = new ListBlobsOptions().setStorageResponseSerializationFormat(StorageResponseSerializationFormat.ARROW); + + Flux response = bc.upload(DATA.getDefaultFlux(), DATA.getDefaultDataSize()) + .then(rehydrate) + .thenMany(ccAsync.listBlobs(options, null)); + + StepVerifier.create(response) + .assertNext(r -> assertEquals(rehydratePriority, r.getProperties().getRehydratePriority())) + .verifyComplete(); + } + + @Test + @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2026-06-06") + public void listBlobsArrowDeserializer() { + String blobName = generateBlobName(); + Map metadata = new HashMap<>(); + metadata.put("testkey", "testvalue"); + + BlockBlobAsyncClient bc = ccAsync.getBlobAsyncClient(blobName).getBlockBlobAsyncClient(); + + AzureBlobStorageImpl impl = new AzureBlobStorageImplBuilder().pipeline(ccAsync.getHttpPipeline()) + .url(ccAsync.getAccountUrl()) + .version(BlobServiceVersion.V2026_06_06.getVersion()) + .buildClient(); + + List include = new ArrayList<>(); + include.add(ListBlobsIncludeItem.METADATA); + + Mono testMono + = bc.uploadWithResponse(DATA.getDefaultFlux(), 7, null, metadata, null, null, null) + .then(impl.getContainers() + .listBlobFlatSegmentApacheArrowWithResponseAsync(containerName, null, null, null, include, null, + null, null, null)) + .flatMap(response -> { + // Verify Content-Type is Arrow + String contentType = response.getDeserializedHeaders().getContentType(); + assertTrue(contentType.contains("application/vnd.apache.arrow.stream"), + "Expected Arrow content type but got: " + contentType); + + // Collect the Flux body into a byte[] and feed it to the deserializer. + return FluxUtil.collectBytesInByteBufferStream(response.getValue()) + .map(bytes -> ArrowBlobListDeserializer.deserialize(new ByteArrayInputStream(bytes))); + }); + + StepVerifier.create(testMono).assertNext(result -> { + // Verify pagination — single blob, no next page + assertNull(result.getNextMarker()); + + // Verify we got exactly one blob + assertEquals(1, result.getBlobItems().size()); + + BlobItemInternal item = result.getBlobItems().get(0); + + // Name + assertNotNull(item.getName()); + assertEquals(blobName, item.getName().getContent()); + + // Properties + assertNotNull(item.getProperties()); + assertEquals(7L, (long) item.getProperties().getContentLength()); + assertEquals("application/octet-stream", item.getProperties().getContentType()); + assertNotNull(item.getProperties().getETag()); + assertNotNull(item.getProperties().getLastModified()); + assertNotNull(item.getProperties().getCreationTime()); + assertEquals(BlobType.BLOCK_BLOB, item.getProperties().getBlobType()); + assertEquals(AccessTier.HOT, item.getProperties().getAccessTier()); + assertTrue(item.getProperties().isAccessTierInferred()); + assertTrue(item.getProperties().isServerEncrypted()); + assertEquals(LeaseStateType.AVAILABLE, item.getProperties().getLeaseState()); + assertEquals(LeaseStatusType.UNLOCKED, item.getProperties().getLeaseStatus()); + assertNotNull(item.getProperties().getContentMd5()); + + // Metadata + assertNotNull(item.getMetadata()); + assertEquals("testvalue", item.getMetadata().get("testkey")); + + // Verify ModelHelper can convert to public BlobItem + BlobItem publicItem = ModelHelper.populateBlobItem(item); + assertEquals(blobName, publicItem.getName()); + assertEquals(7L, (long) publicItem.getProperties().getContentLength()); + }).verifyComplete(); + } + + @Test + @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2026-06-06") + public void listBlobsByHierarchyArrowBasic() { + // Upload blobs in a directory structure + Flux uploads = Flux.concat( + ccAsync.getBlobAsyncClient("dir/blob1") + .getBlockBlobAsyncClient() + .upload(DATA.getDefaultFlux(), DATA.getDefaultDataSize()), + ccAsync.getBlobAsyncClient("dir/blob2") + .getBlockBlobAsyncClient() + .upload(DATA.getDefaultFlux(), DATA.getDefaultDataSize()), + ccAsync.getBlobAsyncClient("topblob") + .getBlockBlobAsyncClient() + .upload(DATA.getDefaultFlux(), DATA.getDefaultDataSize())); + + ListBlobsOptions options + = new ListBlobsOptions().setStorageResponseSerializationFormat(StorageResponseSerializationFormat.ARROW); + + Mono> items + = uploads.then(ccAsync.listBlobsByHierarchy("/", options).collect(Collectors.toList())); + + StepVerifier.create(items).assertNext(list -> { + // Root level: one prefix "dir/" and one blob "topblob" + assertEquals(2, list.size()); + + BlobItem prefixItem = list.stream().filter(BlobItem::isPrefix).findFirst().orElse(null); + BlobItem blobItem = list.stream().filter(i -> !i.isPrefix()).findFirst().orElse(null); + + assertNotNull(prefixItem); + assertEquals("dir/", prefixItem.getName()); + assertTrue(prefixItem.isPrefix()); + + assertNotNull(blobItem); + assertEquals("topblob", blobItem.getName()); + assertFalse(blobItem.isPrefix()); + assertNotNull(blobItem.getProperties()); + assertEquals(DATA.getDefaultDataSize(), blobItem.getProperties().getContentLength()); + assertEquals(BlobType.BLOCK_BLOB, blobItem.getProperties().getBlobType()); + assertNotNull(blobItem.getProperties().getLastModified()); + assertNotNull(blobItem.getProperties().getETag()); + }).verifyComplete(); + } + + @Test + @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2026-06-06") + public void listBlobsByHierarchyArrowWithMetadata() { + String blobName = generateBlobName(); + Map metadata = new HashMap<>(); + metadata.put("testkey", "testvalue"); + + Mono uploads = ccAsync.getBlobAsyncClient("dir/" + blobName) + .getBlockBlobAsyncClient() + .uploadWithResponse(DATA.getDefaultFlux(), DATA.getDefaultDataSize(), null, metadata, null, null, null) + .then(ccAsync.getBlobAsyncClient("topblob") + .getBlockBlobAsyncClient() + .upload(DATA.getDefaultFlux(), DATA.getDefaultDataSize())); + + ListBlobsOptions options + = new ListBlobsOptions().setStorageResponseSerializationFormat(StorageResponseSerializationFormat.ARROW) + .setPrefix("dir/") + .setDetails(new BlobListDetails().setRetrieveMetadata(true)); + + StepVerifier.create(uploads.thenMany(ccAsync.listBlobsByHierarchy("/", options))).assertNext(item -> { + assertFalse(item.isPrefix()); + assertNotNull(item.getMetadata()); + assertEquals("testvalue", item.getMetadata().get("testkey")); + }).verifyComplete(); + } + + @Test + @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2026-06-06") + public void listBlobsByHierarchyArrowPagination() { + // Upload blobs across multiple directories + Flux uploads = Flux.concat( + Flux.range(0, 3) + .flatMap(i -> ccAsync.getBlobAsyncClient("dir" + i + "/blob") + .getBlockBlobAsyncClient() + .upload(DATA.getDefaultFlux(), DATA.getDefaultDataSize())), + ccAsync.getBlobAsyncClient("topblob") + .getBlockBlobAsyncClient() + .upload(DATA.getDefaultFlux(), DATA.getDefaultDataSize())); + + ListBlobsOptions options + = new ListBlobsOptions().setStorageResponseSerializationFormat(StorageResponseSerializationFormat.ARROW) + .setMaxResultsPerPage(1); + + Mono> result + = uploads.then(ccAsync.listBlobsByHierarchy("/", options).byPage().doOnNext(page -> { + assertTrue(page.getValue().size() <= 1); + }).flatMap(page -> Flux.fromIterable(page.getValue())).collectList()); + + // 3 prefixes + 1 blob = 4 items + StepVerifier.create(result).assertNext(allItems -> assertEquals(4, allItems.size())).verifyComplete(); + } + + @Test + @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2026-06-06") + public void listBlobsArrowWithTags() { + // Upload a blob and set tags + String blobName = generateBlobName(); + BlockBlobAsyncClient bc = ccAsync.getBlobAsyncClient(blobName).getBlockBlobAsyncClient(); + + Map tags = new HashMap<>(); + tags.put("tagkey", "tagvalue"); + + ListBlobsOptions options + = new ListBlobsOptions().setStorageResponseSerializationFormat(StorageResponseSerializationFormat.ARROW) + .setDetails(new BlobListDetails().setRetrieveTags(true)); + + Mono upload = bc.upload(DATA.getDefaultFlux(), DATA.getDefaultDataSize()) + .then(ccAsync.getBlobAsyncClient(blobName).setTags(tags)); + + StepVerifier.create(upload.thenMany(ccAsync.listBlobs(options, null))).assertNext(item -> { + assertEquals(blobName, item.getName()); + assertNotNull(item.getTags()); + assertEquals("tagvalue", item.getTags().get("tagkey")); + }).verifyComplete(); + } } diff --git a/sdk/storage/azure-storage-blob/swagger/README.md b/sdk/storage/azure-storage-blob/swagger/README.md index 98afe0c616dc..a69eb1ee871b 100644 --- a/sdk/storage/azure-storage-blob/swagger/README.md +++ b/sdk/storage/azure-storage-blob/swagger/README.md @@ -16,7 +16,7 @@ autorest ### Code generation settings ``` yaml use: '@autorest/java@4.1.63' -input-file: https://raw.githubusercontent.com/seanmcc-msft/azure-rest-api-specs/eb29a830edf5db50758e7d044160c7f18077f7f7/specification/storage/data-plane/Microsoft.BlobStorage/stable/2026-10-06/blob.json +input-file: https://raw.githubusercontent.com/nickliu-msft/azure-rest-api-specs/ab1ec63862fdf4506cfb1cdd4c8105281b5de3f0/specification/storage/data-plane/Microsoft.BlobStorage/stable/2026-10-06/blob.json java: true output-folder: ../ namespace: com.azure.storage.blob @@ -591,6 +591,24 @@ directive: delete $["x-ms-pageable"]; ``` +### Delete Container_ListBlobFlatSegment_ApacheArrow x-ms-pageable as response is raw Arrow stream +``` yaml +directive: +- from: swagger-document + where: $["x-ms-paths"]["/{containerName}?restype=container&comp=list&flat&arrow"].get + transform: > + delete $["x-ms-pageable"]; +``` + +### Delete Container_ListBlobHierarchySegment_ApacheArrow x-ms-pageable as response is raw Arrow stream +``` yaml +directive: +- from: swagger-document + where: $["x-ms-paths"]["/{containerName}?restype=container&comp=list&hierarchy&arrow"].get + transform: > + delete $["x-ms-pageable"]; +``` + ### BlobDeleteType expandable string enum ``` yaml directive: @@ -708,4 +726,3 @@ directive: ]; ``` - diff --git a/sdk/storage/azure-storage-common/src/test-shared/java/com/azure/storage/common/test/shared/TestEnvironment.java b/sdk/storage/azure-storage-common/src/test-shared/java/com/azure/storage/common/test/shared/TestEnvironment.java index 5d9bc1c9dfac..6134a8dbf9ee 100644 --- a/sdk/storage/azure-storage-common/src/test-shared/java/com/azure/storage/common/test/shared/TestEnvironment.java +++ b/sdk/storage/azure-storage-common/src/test-shared/java/com/azure/storage/common/test/shared/TestEnvironment.java @@ -107,8 +107,8 @@ private static TestAccount readTestAccountFromEnvironment(String prefix, TestMod + "AccountKey=%s;EndpointSuffix=core.windows.net", name, key); } } - String blobEndpoint = String.format(SCHEME + "://%s.blob.core.windows.net", name); - String blobEndpointSecondary = String.format(SCHEME + "://%s-secondary.blob.core.windows.net", name); + String blobEndpoint = String.format(SCHEME + "://%s." + "blob."+ "preprod." +"core.windows.net", name); + String blobEndpointSecondary = String.format(SCHEME + "://%s-secondary." + "preprod." +"core.windows.net", name); String dataLakeEndpoint = String.format(SCHEME + "://%s.dfs.core.windows.net", name); String queueEndpoint = String.format(SCHEME + "://%s.queue.core.windows.net", name); String fileEndpoint = String.format(SCHEME + "://%s.file.core.windows.net", name);