From 6a42a8e42b11a53b7015dc3f20b9a4d540683c6d Mon Sep 17 00:00:00 2001 From: Isabelle Date: Tue, 16 Jun 2026 21:53:26 -0700 Subject: [PATCH 1/5] fixes and tests --- sdk/storage/azure-storage-blob/CHANGELOG.md | 8 ++ ...geSeekableByteChannelBlobReadBehavior.java | 28 ++++++ ...kableByteChannelBlobReadBehaviorTests.java | 94 +++++++++++++++++++ 3 files changed, 130 insertions(+) diff --git a/sdk/storage/azure-storage-blob/CHANGELOG.md b/sdk/storage/azure-storage-blob/CHANGELOG.md index 574c8c57ebff..1c33e9db7b82 100644 --- a/sdk/storage/azure-storage-blob/CHANGELOG.md +++ b/sdk/storage/azure-storage-blob/CHANGELOG.md @@ -7,6 +7,14 @@ ### Breaking Changes ### Bugs Fixed +- Fixed an issue where `BlobClientBase.openSeekableByteChannelRead` issued an unnecessary HTTP request (resulting + in an HTTP 416 response) after the entire blob had already been returned in the initial range download. When the + channel is opened with ETag consistency control (the default) the read behavior now short-circuits to end-of-file + once the known resource length is reached, avoiding the extra round trip. +- Fixed an issue where a transport-level failure while streaming the body of the trailing HTTP 416 response from + `BlobClientBase.openSeekableByteChannelRead` (for example "Connection reset by peer") could propagate out of the + channel even though all of the blob's content had already been delivered to the caller. The read behavior now + logs a warning and signals end-of-file when such an error occurs at or past the known end of the resource. ### Other Changes diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/specialized/StorageSeekableByteChannelBlobReadBehavior.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/specialized/StorageSeekableByteChannelBlobReadBehavior.java index 5700e1e7dd36..094713196ade 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/specialized/StorageSeekableByteChannelBlobReadBehavior.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/specialized/StorageSeekableByteChannelBlobReadBehavior.java @@ -71,6 +71,15 @@ public int read(ByteBuffer dst, long sourceOffset) throws IOException { initialBufferPosition = null; } + // If the request is at or past the known end of the resource and the blob content is locked via an + // If-Match ETag, the blob cannot have grown without invalidating the precondition. Short-circuit and + // signal end-of-file rather than issuing a request that the service will reject with HTTP 416. This + // avoids an unnecessary round trip (and the failure modes that come with streaming the 416 response + // body, such as the connection being reset by the service). + if (sourceOffset >= resourceLength && isEtagLocked()) { + return -1; + } + int initialPosition = dst.position(); try (ByteBufferBackedOutputStreamUtil dstStream = new ByteBufferBackedOutputStreamUtil(dst)) { @@ -90,9 +99,28 @@ public int read(ByteBuffer dst, long sourceOffset) throws IOException { return sourceOffset < resourceLength ? 0 : -1; } throw LOGGER.logExceptionAsError(e); + } catch (RuntimeException e) { + // Reading the body of an HTTP 416 response can fail with transport-level errors (for example + // 'Connection reset by peer' wrapped in reactor's ReactiveException). When the requested offset is + // already at or past the known end of the resource, no data could have been returned anyway, so log + // the failure and signal end-of-file instead of propagating an exception to the caller that has + // already received all of the blob's content. + if (sourceOffset >= resourceLength) { + LOGGER.warning("Ignoring error encountered while issuing a read at or past the end of the blob; " + + "treating as end-of-file because the resource length is already known.", e); + return -1; + } + throw LOGGER.logExceptionAsError(e); } } + /** + * @return Whether the request conditions on this behavior lock the blob's content via an If-Match ETag. + */ + private boolean isEtagLocked() { + return requestConditions != null && requestConditions.getIfMatch() != null; + } + /** * Reads the cached byte buffer into the provided byte buffer and clears the cache. * @param dst Destination for read contents. diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/StorageSeekableByteChannelBlobReadBehaviorTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/StorageSeekableByteChannelBlobReadBehaviorTests.java index 5ccc9dfc1ea4..63c097ae2639 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/StorageSeekableByteChannelBlobReadBehaviorTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/StorageSeekableByteChannelBlobReadBehaviorTests.java @@ -35,9 +35,11 @@ import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -273,4 +275,96 @@ void readDetectsBlobGrowth() throws IOException { assertEquals(buffer.capacity(), buffer.position()); TestUtils.assertArraysEqual(data, halfLength, buffer.array(), 0, data.length - halfLength); } + + /** + * When the request conditions lock the blob via an If-Match ETag, a read at or past the known end of the + * resource must short-circuit to EOF without issuing a service call (which the service would reject with an + * HTTP 416 response). + */ + @Test + public void readPastEndShortCircuitsWhenETagLocked() throws IOException { + BlobClientBase client = Mockito.mock(BlobClientBase.class); + BlobRequestConditions conditions = new BlobRequestConditions().setIfMatch("\"0xETAG\""); + + long resourceLength = Constants.KB; + StorageSeekableByteChannelBlobReadBehavior behavior = new StorageSeekableByteChannelBlobReadBehavior(client, + ByteBuffer.allocate(0), -1, resourceLength, conditions); + + // when: "Reading at the known end of the resource" + int readAtEnd = behavior.read(ByteBuffer.allocate(Constants.KB), resourceLength); + + // then: "EOF is signaled without any service call" + assertEquals(-1, readAtEnd); + verify(client, never()).downloadStreamWithResponse(any(), any(), any(), any(), anyBoolean(), any(), any()); + + // when: "Reading past the known end of the resource" + int readPastEnd = behavior.read(ByteBuffer.allocate(Constants.KB), resourceLength + Constants.KB); + + // then: "EOF is still signaled without any service call" + assertEquals(-1, readPastEnd); + verify(client, never()).downloadStreamWithResponse(any(), any(), any(), any(), anyBoolean(), any(), any()); + } + + /** + * When the blob is not ETag-locked, a read past the end must still issue a request so the behavior can + * detect blob growth (existing contract preserved). + */ + @Test + public void readPastEndIssuesRequestWhenNotETagLocked() throws IOException { + BlobClientBase client = Mockito.mock(BlobClientBase.class); + long resourceLength = Constants.KB; + Mockito.when(client.downloadStreamWithResponse(any(), any(), any(), any(), anyBoolean(), any(), any())) + .thenReturn(createMockDownloadResponse( + "bytes " + resourceLength + "-" + (resourceLength + Constants.KB - 1) + "/" + 2 * Constants.KB)); + + StorageSeekableByteChannelBlobReadBehavior behavior + = new StorageSeekableByteChannelBlobReadBehavior(client, ByteBuffer.allocate(0), -1, resourceLength, null); + + // when: "Reading past the known end of the resource without an ETag lock" + behavior.read(ByteBuffer.allocate(Constants.KB), resourceLength); + + // then: "A service call is issued (existing growth-detection behavior preserved)" + verify(client, times(1)).downloadStreamWithResponse(any(), any(), any(), any(), anyBoolean(), any(), any()); + } + + /** + * If the underlying download throws a non-{@code BlobStorageException} (for example, the connection is + * reset while streaming the body of a 416 response) and the caller is already at or past the known end of + * the resource, the behavior should swallow the error, log a warning, and signal EOF rather than throwing. + */ + @Test + public void readPastEndSwallowsTransportErrorAndSignalsEof() throws IOException { + BlobClientBase client = Mockito.mock(BlobClientBase.class); + long resourceLength = Constants.KB; + Mockito.when(client.downloadStreamWithResponse(any(), any(), any(), any(), anyBoolean(), any(), any())) + .thenThrow(new RuntimeException("Connection reset by peer")); + + StorageSeekableByteChannelBlobReadBehavior behavior + = new StorageSeekableByteChannelBlobReadBehavior(client, ByteBuffer.allocate(0), -1, resourceLength, null); + + // when: "Reading past the known end and the download fails with a transport-level error" + int read = behavior.read(ByteBuffer.allocate(Constants.KB), resourceLength); + + // then: "EOF is signaled instead of the exception propagating" + assertEquals(-1, read); + verify(client, times(1)).downloadStreamWithResponse(any(), any(), any(), any(), anyBoolean(), any(), any()); + } + + /** + * Non-{@code BlobStorageException} failures that occur while reading within the known bounds of the resource + * must continue to surface as exceptions, since some bytes the caller asked for could not be retrieved. + */ + @Test + public void readWithinResourcePropagatesTransportError() { + BlobClientBase client = Mockito.mock(BlobClientBase.class); + long resourceLength = Constants.KB; + Mockito.when(client.downloadStreamWithResponse(any(), any(), any(), any(), anyBoolean(), any(), any())) + .thenThrow(new RuntimeException("Connection reset by peer")); + + StorageSeekableByteChannelBlobReadBehavior behavior + = new StorageSeekableByteChannelBlobReadBehavior(client, ByteBuffer.allocate(0), -1, resourceLength, null); + + // Reading within the known resource range should still surface the error. + assertThrows(RuntimeException.class, () -> behavior.read(ByteBuffer.allocate(Constants.KB), 0)); + } } From d3f9b983ec61bada866fbb3975b5e92379ca5895 Mon Sep 17 00:00:00 2001 From: Isabelle <141270045+ibrandes@users.noreply.github.com> Date: Tue, 16 Jun 2026 22:14:17 -0700 Subject: [PATCH 2/5] Apply suggestions from code review Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- sdk/storage/azure-storage-blob/CHANGELOG.md | 2 +- ...geSeekableByteChannelBlobReadBehavior.java | 9 +++- ...kableByteChannelBlobReadBehaviorTests.java | 49 ++++++++++++------- 3 files changed, 40 insertions(+), 20 deletions(-) diff --git a/sdk/storage/azure-storage-blob/CHANGELOG.md b/sdk/storage/azure-storage-blob/CHANGELOG.md index 3b0155f5753a..1a4ec57e5034 100644 --- a/sdk/storage/azure-storage-blob/CHANGELOG.md +++ b/sdk/storage/azure-storage-blob/CHANGELOG.md @@ -9,7 +9,7 @@ ### Bugs Fixed - Fixed an issue where `BlobClientBase.openSeekableByteChannelRead` issued an unnecessary HTTP request (resulting in an HTTP 416 response) after the entire blob had already been returned in the initial range download. When the - channel is opened with ETag consistency control (the default) the read behavior now short-circuits to end-of-file + channel is opened with ETag consistency control (the default), the read behavior now short-circuits to end-of-file once the known resource length is reached, avoiding the extra round trip. - Fixed an issue where a transport-level failure while streaming the body of the trailing HTTP 416 response from `BlobClientBase.openSeekableByteChannelRead` (for example "Connection reset by peer") could propagate out of the diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/specialized/StorageSeekableByteChannelBlobReadBehavior.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/specialized/StorageSeekableByteChannelBlobReadBehavior.java index 094713196ade..76f1cce570bb 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/specialized/StorageSeekableByteChannelBlobReadBehavior.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/specialized/StorageSeekableByteChannelBlobReadBehavior.java @@ -117,10 +117,15 @@ public int read(ByteBuffer dst, long sourceOffset) throws IOException { /** * @return Whether the request conditions on this behavior lock the blob's content via an If-Match ETag. */ - private boolean isEtagLocked() { - return requestConditions != null && requestConditions.getIfMatch() != null; +private boolean isEtagLocked() { + if (requestConditions == null) { + return false; } + String ifMatch = requestConditions.getIfMatch(); + return !CoreUtils.isNullOrEmpty(ifMatch) && !"*".equals(ifMatch.trim()); +} + /** * Reads the cached byte buffer into the provided byte buffer and clears the cache. * @param dst Destination for read contents. diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/StorageSeekableByteChannelBlobReadBehaviorTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/StorageSeekableByteChannelBlobReadBehaviorTests.java index 63c097ae2639..eec516938f32 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/StorageSeekableByteChannelBlobReadBehaviorTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/StorageSeekableByteChannelBlobReadBehaviorTests.java @@ -282,28 +282,43 @@ void readDetectsBlobGrowth() throws IOException { * HTTP 416 response). */ @Test - public void readPastEndShortCircuitsWhenETagLocked() throws IOException { - BlobClientBase client = Mockito.mock(BlobClientBase.class); - BlobRequestConditions conditions = new BlobRequestConditions().setIfMatch("\"0xETAG\""); +@Test +public void readPastEndShortCircuitsWhenETagLocked() throws IOException { + BlobClientBase client = Mockito.mock(BlobClientBase.class); - long resourceLength = Constants.KB; - StorageSeekableByteChannelBlobReadBehavior behavior = new StorageSeekableByteChannelBlobReadBehavior(client, - ByteBuffer.allocate(0), -1, resourceLength, conditions); + long resourceLength = Constants.KB; + BlobRequestConditions conditions = new BlobRequestConditions().setIfMatch("0xETAG"); + StorageSeekableByteChannelBlobReadBehavior behavior = new StorageSeekableByteChannelBlobReadBehavior(client, + ByteBuffer.allocate(0), -1, resourceLength, conditions); - // when: "Reading at the known end of the resource" - int readAtEnd = behavior.read(ByteBuffer.allocate(Constants.KB), resourceLength); + // when: "Reading at the known end of the resource" + int readAtEnd = behavior.read(ByteBuffer.allocate(Constants.KB), resourceLength); - // then: "EOF is signaled without any service call" - assertEquals(-1, readAtEnd); - verify(client, never()).downloadStreamWithResponse(any(), any(), any(), any(), anyBoolean(), any(), any()); + // then: "EOF is signaled without any service call" + assertEquals(-1, readAtEnd); + verify(client, never()).downloadStreamWithResponse(any(), any(), any(), any(), anyBoolean(), any(), any()); - // when: "Reading past the known end of the resource" - int readPastEnd = behavior.read(ByteBuffer.allocate(Constants.KB), resourceLength + Constants.KB); + // when: "Reading past the known end of the resource" + int readPastEnd = behavior.read(ByteBuffer.allocate(Constants.KB), resourceLength + Constants.KB); - // then: "EOF is still signaled without any service call" - assertEquals(-1, readPastEnd); - verify(client, never()).downloadStreamWithResponse(any(), any(), any(), any(), anyBoolean(), any(), any()); - } + // then: "EOF is still signaled without any service call" + assertEquals(-1, readPastEnd); + verify(client, never()).downloadStreamWithResponse(any(), any(), any(), any(), anyBoolean(), any(), any()); + + // If-Match="*" is an existence precondition (not a specific ETag lock), so growth-detection behavior should be + // preserved and a request should still be issued. + Mockito.when(client.downloadStreamWithResponse(any(), any(), any(), any(), anyBoolean(), any(), any())) + .thenReturn(createMockDownloadResponse( + "bytes " + resourceLength + "-" + (resourceLength + Constants.KB - 1) + "/" + 2 * Constants.KB)); + + BlobRequestConditions ifMatchStar = new BlobRequestConditions().setIfMatch("*"); + StorageSeekableByteChannelBlobReadBehavior starBehavior = new StorageSeekableByteChannelBlobReadBehavior(client, + ByteBuffer.allocate(0), -1, resourceLength, ifMatchStar); + + starBehavior.read(ByteBuffer.allocate(Constants.KB), resourceLength); + + verify(client, times(1)).downloadStreamWithResponse(any(), any(), any(), any(), anyBoolean(), any(), any()); +} /** * When the blob is not ETag-locked, a read past the end must still issue a request so the behavior can From 62d4306910eeb147581475143f517ee9c099db82 Mon Sep 17 00:00:00 2001 From: Isabelle Date: Tue, 16 Jun 2026 22:18:16 -0700 Subject: [PATCH 3/5] adding test recordings --- sdk/storage/azure-storage-blob/assets.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/storage/azure-storage-blob/assets.json b/sdk/storage/azure-storage-blob/assets.json index 8cad139f33ff..7b04faada68a 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_47f4243e59" + "Tag": "java/storage/azure-storage-blob_552df730ec" } From 2a2f21a99708c4f4baefd58c644ea323dd601bd2 Mon Sep 17 00:00:00 2001 From: Isabelle Date: Wed, 17 Jun 2026 08:30:04 -0700 Subject: [PATCH 4/5] formatting --- ...kableByteChannelBlobReadBehaviorTests.java | 55 +++++++++---------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/StorageSeekableByteChannelBlobReadBehaviorTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/StorageSeekableByteChannelBlobReadBehaviorTests.java index eec516938f32..a16e10e2b107 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/StorageSeekableByteChannelBlobReadBehaviorTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/StorageSeekableByteChannelBlobReadBehaviorTests.java @@ -282,43 +282,42 @@ void readDetectsBlobGrowth() throws IOException { * HTTP 416 response). */ @Test -@Test -public void readPastEndShortCircuitsWhenETagLocked() throws IOException { - BlobClientBase client = Mockito.mock(BlobClientBase.class); + public void readPastEndShortCircuitsWhenETagLocked() throws IOException { + BlobClientBase client = Mockito.mock(BlobClientBase.class); - long resourceLength = Constants.KB; - BlobRequestConditions conditions = new BlobRequestConditions().setIfMatch("0xETAG"); - StorageSeekableByteChannelBlobReadBehavior behavior = new StorageSeekableByteChannelBlobReadBehavior(client, - ByteBuffer.allocate(0), -1, resourceLength, conditions); + long resourceLength = Constants.KB; + BlobRequestConditions conditions = new BlobRequestConditions().setIfMatch("0xETAG"); + StorageSeekableByteChannelBlobReadBehavior behavior = new StorageSeekableByteChannelBlobReadBehavior(client, + ByteBuffer.allocate(0), -1, resourceLength, conditions); - // when: "Reading at the known end of the resource" - int readAtEnd = behavior.read(ByteBuffer.allocate(Constants.KB), resourceLength); + // when: "Reading at the known end of the resource" + int readAtEnd = behavior.read(ByteBuffer.allocate(Constants.KB), resourceLength); - // then: "EOF is signaled without any service call" - assertEquals(-1, readAtEnd); - verify(client, never()).downloadStreamWithResponse(any(), any(), any(), any(), anyBoolean(), any(), any()); + // then: "EOF is signaled without any service call" + assertEquals(-1, readAtEnd); + verify(client, never()).downloadStreamWithResponse(any(), any(), any(), any(), anyBoolean(), any(), any()); - // when: "Reading past the known end of the resource" - int readPastEnd = behavior.read(ByteBuffer.allocate(Constants.KB), resourceLength + Constants.KB); + // when: "Reading past the known end of the resource" + int readPastEnd = behavior.read(ByteBuffer.allocate(Constants.KB), resourceLength + Constants.KB); - // then: "EOF is still signaled without any service call" - assertEquals(-1, readPastEnd); - verify(client, never()).downloadStreamWithResponse(any(), any(), any(), any(), anyBoolean(), any(), any()); + // then: "EOF is still signaled without any service call" + assertEquals(-1, readPastEnd); + verify(client, never()).downloadStreamWithResponse(any(), any(), any(), any(), anyBoolean(), any(), any()); - // If-Match="*" is an existence precondition (not a specific ETag lock), so growth-detection behavior should be - // preserved and a request should still be issued. - Mockito.when(client.downloadStreamWithResponse(any(), any(), any(), any(), anyBoolean(), any(), any())) - .thenReturn(createMockDownloadResponse( - "bytes " + resourceLength + "-" + (resourceLength + Constants.KB - 1) + "/" + 2 * Constants.KB)); + // If-Match="*" is an existence precondition (not a specific ETag lock), so growth-detection behavior should be + // preserved and a request should still be issued. + Mockito.when(client.downloadStreamWithResponse(any(), any(), any(), any(), anyBoolean(), any(), any())) + .thenReturn(createMockDownloadResponse( + "bytes " + resourceLength + "-" + (resourceLength + Constants.KB - 1) + "/" + 2 * Constants.KB)); - BlobRequestConditions ifMatchStar = new BlobRequestConditions().setIfMatch("*"); - StorageSeekableByteChannelBlobReadBehavior starBehavior = new StorageSeekableByteChannelBlobReadBehavior(client, - ByteBuffer.allocate(0), -1, resourceLength, ifMatchStar); + BlobRequestConditions ifMatchStar = new BlobRequestConditions().setIfMatch("*"); + StorageSeekableByteChannelBlobReadBehavior starBehavior = new StorageSeekableByteChannelBlobReadBehavior(client, + ByteBuffer.allocate(0), -1, resourceLength, ifMatchStar); - starBehavior.read(ByteBuffer.allocate(Constants.KB), resourceLength); + starBehavior.read(ByteBuffer.allocate(Constants.KB), resourceLength); - verify(client, times(1)).downloadStreamWithResponse(any(), any(), any(), any(), anyBoolean(), any(), any()); -} + verify(client, times(1)).downloadStreamWithResponse(any(), any(), any(), any(), anyBoolean(), any(), any()); + } /** * When the blob is not ETag-locked, a read past the end must still issue a request so the behavior can From cf27db842bb9ac45af4cc3a06d15ed0f772118d7 Mon Sep 17 00:00:00 2001 From: Isabelle Date: Wed, 17 Jun 2026 09:48:18 -0700 Subject: [PATCH 5/5] style --- ...StorageSeekableByteChannelBlobReadBehavior.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/specialized/StorageSeekableByteChannelBlobReadBehavior.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/specialized/StorageSeekableByteChannelBlobReadBehavior.java index 76f1cce570bb..853d567bf23a 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/specialized/StorageSeekableByteChannelBlobReadBehavior.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/specialized/StorageSeekableByteChannelBlobReadBehavior.java @@ -117,14 +117,14 @@ public int read(ByteBuffer dst, long sourceOffset) throws IOException { /** * @return Whether the request conditions on this behavior lock the blob's content via an If-Match ETag. */ -private boolean isEtagLocked() { - if (requestConditions == null) { - return false; - } + private boolean isEtagLocked() { + if (requestConditions == null) { + return false; + } - String ifMatch = requestConditions.getIfMatch(); - return !CoreUtils.isNullOrEmpty(ifMatch) && !"*".equals(ifMatch.trim()); -} + String ifMatch = requestConditions.getIfMatch(); + return !CoreUtils.isNullOrEmpty(ifMatch) && !"*".equals(ifMatch.trim()); + } /** * Reads the cached byte buffer into the provided byte buffer and clears the cache.