From 1d35c116c05dbfc387cb0e97ef72e9369aa40374 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 11 Jul 2025 14:21:41 -0400 Subject: [PATCH 01/15] chore(main): release 2.53.4-SNAPSHOT (#3192) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- gapic-google-cloud-storage-v2/pom.xml | 4 ++-- google-cloud-storage-bom/pom.xml | 16 ++++++++-------- google-cloud-storage-control/pom.xml | 4 ++-- google-cloud-storage/pom.xml | 4 ++-- grpc-google-cloud-storage-control-v2/pom.xml | 4 ++-- grpc-google-cloud-storage-v2/pom.xml | 4 ++-- pom.xml | 16 ++++++++-------- proto-google-cloud-storage-control-v2/pom.xml | 4 ++-- proto-google-cloud-storage-v2/pom.xml | 4 ++-- samples/snapshot/pom.xml | 6 +++--- storage-shared-benchmarking/pom.xml | 4 ++-- versions.txt | 14 +++++++------- 12 files changed, 42 insertions(+), 42 deletions(-) diff --git a/gapic-google-cloud-storage-v2/pom.xml b/gapic-google-cloud-storage-v2/pom.xml index d65f75a0d..3a601c38a 100644 --- a/gapic-google-cloud-storage-v2/pom.xml +++ b/gapic-google-cloud-storage-v2/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc gapic-google-cloud-storage-v2 - 2.53.3 + 2.53.4-SNAPSHOT gapic-google-cloud-storage-v2 GRPC library for gapic-google-cloud-storage-v2 com.google.cloud google-cloud-storage-parent - 2.53.3 + 2.53.4-SNAPSHOT diff --git a/google-cloud-storage-bom/pom.xml b/google-cloud-storage-bom/pom.xml index 0f9947023..0c9198ddf 100644 --- a/google-cloud-storage-bom/pom.xml +++ b/google-cloud-storage-bom/pom.xml @@ -19,7 +19,7 @@ 4.0.0 com.google.cloud google-cloud-storage-bom - 2.53.3 + 2.53.4-SNAPSHOT pom com.google.cloud @@ -69,37 +69,37 @@ com.google.cloud google-cloud-storage - 2.53.3 + 2.53.4-SNAPSHOT com.google.api.grpc gapic-google-cloud-storage-v2 - 2.53.3 + 2.53.4-SNAPSHOT com.google.api.grpc grpc-google-cloud-storage-v2 - 2.53.3 + 2.53.4-SNAPSHOT com.google.api.grpc proto-google-cloud-storage-v2 - 2.53.3 + 2.53.4-SNAPSHOT com.google.cloud google-cloud-storage-control - 2.53.3 + 2.53.4-SNAPSHOT com.google.api.grpc grpc-google-cloud-storage-control-v2 - 2.53.3 + 2.53.4-SNAPSHOT com.google.api.grpc proto-google-cloud-storage-control-v2 - 2.53.3 + 2.53.4-SNAPSHOT diff --git a/google-cloud-storage-control/pom.xml b/google-cloud-storage-control/pom.xml index 7da8027ea..416ffa54e 100644 --- a/google-cloud-storage-control/pom.xml +++ b/google-cloud-storage-control/pom.xml @@ -5,13 +5,13 @@ 4.0.0 com.google.cloud google-cloud-storage-control - 2.53.3 + 2.53.4-SNAPSHOT google-cloud-storage-control GRPC library for google-cloud-storage-control com.google.cloud google-cloud-storage-parent - 2.53.3 + 2.53.4-SNAPSHOT diff --git a/google-cloud-storage/pom.xml b/google-cloud-storage/pom.xml index 52d523351..1f34751ce 100644 --- a/google-cloud-storage/pom.xml +++ b/google-cloud-storage/pom.xml @@ -2,7 +2,7 @@ 4.0.0 google-cloud-storage - 2.53.3 + 2.53.4-SNAPSHOT jar Google Cloud Storage https://github.com/googleapis/java-storage @@ -12,7 +12,7 @@ com.google.cloud google-cloud-storage-parent - 2.53.3 + 2.53.4-SNAPSHOT google-cloud-storage diff --git a/grpc-google-cloud-storage-control-v2/pom.xml b/grpc-google-cloud-storage-control-v2/pom.xml index a1b43ba33..9e1627edd 100644 --- a/grpc-google-cloud-storage-control-v2/pom.xml +++ b/grpc-google-cloud-storage-control-v2/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc grpc-google-cloud-storage-control-v2 - 2.53.3 + 2.53.4-SNAPSHOT grpc-google-cloud-storage-control-v2 GRPC library for google-cloud-storage com.google.cloud google-cloud-storage-parent - 2.53.3 + 2.53.4-SNAPSHOT diff --git a/grpc-google-cloud-storage-v2/pom.xml b/grpc-google-cloud-storage-v2/pom.xml index 666915e93..a744a8f4a 100644 --- a/grpc-google-cloud-storage-v2/pom.xml +++ b/grpc-google-cloud-storage-v2/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc grpc-google-cloud-storage-v2 - 2.53.3 + 2.53.4-SNAPSHOT grpc-google-cloud-storage-v2 GRPC library for grpc-google-cloud-storage-v2 com.google.cloud google-cloud-storage-parent - 2.53.3 + 2.53.4-SNAPSHOT diff --git a/pom.xml b/pom.xml index eb2760c5b..818bf4e45 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.google.cloud google-cloud-storage-parent pom - 2.53.3 + 2.53.4-SNAPSHOT Storage Parent https://github.com/googleapis/java-storage @@ -82,7 +82,7 @@ com.google.cloud google-cloud-storage - 2.53.3 + 2.53.4-SNAPSHOT com.google.apis @@ -104,32 +104,32 @@ com.google.api.grpc proto-google-cloud-storage-v2 - 2.53.3 + 2.53.4-SNAPSHOT com.google.api.grpc grpc-google-cloud-storage-v2 - 2.53.3 + 2.53.4-SNAPSHOT com.google.api.grpc gapic-google-cloud-storage-v2 - 2.53.3 + 2.53.4-SNAPSHOT com.google.api.grpc grpc-google-cloud-storage-control-v2 - 2.53.3 + 2.53.4-SNAPSHOT com.google.api.grpc proto-google-cloud-storage-control-v2 - 2.53.3 + 2.53.4-SNAPSHOT com.google.cloud google-cloud-storage-control - 2.53.3 + 2.53.4-SNAPSHOT com.google.cloud diff --git a/proto-google-cloud-storage-control-v2/pom.xml b/proto-google-cloud-storage-control-v2/pom.xml index cc1058abc..cca819358 100644 --- a/proto-google-cloud-storage-control-v2/pom.xml +++ b/proto-google-cloud-storage-control-v2/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc proto-google-cloud-storage-control-v2 - 2.53.3 + 2.53.4-SNAPSHOT proto-google-cloud-storage-control-v2 Proto library for proto-google-cloud-storage-control-v2 com.google.cloud google-cloud-storage-parent - 2.53.3 + 2.53.4-SNAPSHOT diff --git a/proto-google-cloud-storage-v2/pom.xml b/proto-google-cloud-storage-v2/pom.xml index a0cb90f15..6fe5a4cbf 100644 --- a/proto-google-cloud-storage-v2/pom.xml +++ b/proto-google-cloud-storage-v2/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc proto-google-cloud-storage-v2 - 2.53.3 + 2.53.4-SNAPSHOT proto-google-cloud-storage-v2 PROTO library for proto-google-cloud-storage-v2 com.google.cloud google-cloud-storage-parent - 2.53.3 + 2.53.4-SNAPSHOT diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml index 2befe325c..3fc84439a 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,12 +28,12 @@ com.google.cloud google-cloud-storage - 2.53.3 + 2.53.4-SNAPSHOT com.google.cloud google-cloud-storage-control - 2.53.3 + 2.53.4-SNAPSHOT compile @@ -70,7 +70,7 @@ com.google.cloud google-cloud-storage - 2.53.3 + 2.53.4-SNAPSHOT tests test diff --git a/storage-shared-benchmarking/pom.xml b/storage-shared-benchmarking/pom.xml index fe14e44ef..b55be369d 100644 --- a/storage-shared-benchmarking/pom.xml +++ b/storage-shared-benchmarking/pom.xml @@ -10,7 +10,7 @@ com.google.cloud google-cloud-storage-parent - 2.53.3 + 2.53.4-SNAPSHOT @@ -31,7 +31,7 @@ com.google.cloud google-cloud-storage - 2.53.3 + 2.53.4-SNAPSHOT tests diff --git a/versions.txt b/versions.txt index 1e5fcdf88..70560e648 100644 --- a/versions.txt +++ b/versions.txt @@ -1,10 +1,10 @@ # Format: # module:released-version:current-version -google-cloud-storage:2.53.3:2.53.3 -gapic-google-cloud-storage-v2:2.53.3:2.53.3 -grpc-google-cloud-storage-v2:2.53.3:2.53.3 -proto-google-cloud-storage-v2:2.53.3:2.53.3 -google-cloud-storage-control:2.53.3:2.53.3 -proto-google-cloud-storage-control-v2:2.53.3:2.53.3 -grpc-google-cloud-storage-control-v2:2.53.3:2.53.3 +google-cloud-storage:2.53.3:2.53.4-SNAPSHOT +gapic-google-cloud-storage-v2:2.53.3:2.53.4-SNAPSHOT +grpc-google-cloud-storage-v2:2.53.3:2.53.4-SNAPSHOT +proto-google-cloud-storage-v2:2.53.3:2.53.4-SNAPSHOT +google-cloud-storage-control:2.53.3:2.53.4-SNAPSHOT +proto-google-cloud-storage-control-v2:2.53.3:2.53.4-SNAPSHOT +grpc-google-cloud-storage-control-v2:2.53.3:2.53.4-SNAPSHOT From 14f62667c8083e6287024e0971c3e078f2a953ec Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 18 Jul 2025 17:32:55 +0200 Subject: [PATCH 02/15] test(deps): update dependency io.github.classgraph:classgraph to v4.8.181 (#3195) --- google-cloud-storage/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/google-cloud-storage/pom.xml b/google-cloud-storage/pom.xml index 1f34751ce..c2540d1f5 100644 --- a/google-cloud-storage/pom.xml +++ b/google-cloud-storage/pom.xml @@ -331,7 +331,7 @@ io.github.classgraph classgraph - 4.8.180 + 4.8.181 test From f8dcec37dea827d9ae540e770713dfc0f7a73967 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 18 Jul 2025 17:33:25 +0200 Subject: [PATCH 03/15] test(deps): update cross product test dependencies (#3194) --- google-cloud-storage/pom.xml | 6 +++--- pom.xml | 2 +- samples/install-without-bom/pom.xml | 4 ++-- samples/snapshot/pom.xml | 4 ++-- samples/snippets/pom.xml | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/google-cloud-storage/pom.xml b/google-cloud-storage/pom.xml index c2540d1f5..13e44fd0b 100644 --- a/google-cloud-storage/pom.xml +++ b/google-cloud-storage/pom.xml @@ -16,7 +16,7 @@ google-cloud-storage - 1.122.2 + 1.123.0 @@ -239,14 +239,14 @@ com.google.api.grpc proto-google-cloud-kms-v1 - 0.161.0 + 0.162.0 test com.google.cloud google-cloud-kms - 2.70.0 + 2.71.0 test diff --git a/pom.xml b/pom.xml index 818bf4e45..f909ec579 100644 --- a/pom.xml +++ b/pom.xml @@ -92,7 +92,7 @@ com.google.cloud google-cloud-pubsub - 1.140.2 + 1.141.0 test diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml index c38122644..2769ffaf0 100644 --- a/samples/install-without-bom/pom.xml +++ b/samples/install-without-bom/pom.xml @@ -66,13 +66,13 @@ com.google.cloud google-cloud-pubsub - 1.140.2 + 1.141.0 test com.google.cloud google-cloud-kms - 2.70.0 + 2.71.0 test diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml index 3fc84439a..40c96caaa 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -58,13 +58,13 @@ com.google.cloud google-cloud-pubsub - 1.140.2 + 1.141.0 test com.google.cloud google-cloud-kms - 2.70.0 + 2.71.0 test diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml index d57d6b014..2eac738b3 100644 --- a/samples/snippets/pom.xml +++ b/samples/snippets/pom.xml @@ -76,13 +76,13 @@ com.google.cloud google-cloud-pubsub - 1.140.2 + 1.141.0 test com.google.cloud google-cloud-kms - 2.70.0 + 2.71.0 test From 9a01288d412466a58d3288e90ab18b974c36bfd7 Mon Sep 17 00:00:00 2001 From: cloud-java-bot <122572305+cloud-java-bot@users.noreply.github.com> Date: Fri, 18 Jul 2025 11:51:40 -0400 Subject: [PATCH 04/15] chore: Update generation configuration at Thu Jul 17 02:36:35 UTC 2025 (#3190) BEGIN_COMMIT_OVERRIDE BEGIN_NESTED_COMMIT chore: Add new field `contexts` for Object Contexts in message `Object` PiperOrigin-RevId: 781971065 Source Link: [googleapis/googleapis@f2a87ff](https://github.com/googleapis/googleapis/commit/f2a87ff9836e96a7d37501128134ff34eb486d2d) END_NESTED_COMMIT BEGIN_NESTED_COMMIT chore: Add new field `filter` for Object Contexts in message `ListObjectsRequest` PiperOrigin-RevId: 781971065 Source Link: [googleapis/googleapis@f2a87ff](https://github.com/googleapis/googleapis/commit/f2a87ff9836e96a7d37501128134ff34eb486d2d) END_NESTED_COMMIT END_COMMIT_OVERRIDE --- .../hermetic_library_generation.yaml | 2 +- .../com/google/storage/v2/StorageClient.java | 3 + .../com.google.storage.v2/reflect-config.json | 36 + .../google/storage/v2/StorageClientTest.java | 10 + generation_config.yaml | 2 +- .../google/storage/v2/ListObjectsRequest.java | 203 +++ .../v2/ListObjectsRequestOrBuilder.java | 30 + .../java/com/google/storage/v2/Object.java | 507 +++++-- .../com/google/storage/v2/ObjectContexts.java | 902 ++++++++++++ .../storage/v2/ObjectContextsOrBuilder.java | 99 ++ .../v2/ObjectCustomContextPayload.java | 1239 +++++++++++++++++ .../ObjectCustomContextPayloadOrBuilder.java | 132 ++ .../google/storage/v2/ObjectOrBuilder.java | 49 + .../com/google/storage/v2/StorageProto.java | 314 +++-- .../proto/google/storage/v2/storage.proto | 31 + 15 files changed, 3343 insertions(+), 216 deletions(-) create mode 100644 proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectContexts.java create mode 100644 proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectContextsOrBuilder.java create mode 100644 proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectCustomContextPayload.java create mode 100644 proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectCustomContextPayloadOrBuilder.java diff --git a/.github/workflows/hermetic_library_generation.yaml b/.github/workflows/hermetic_library_generation.yaml index 4ce1c236a..b984ab43a 100644 --- a/.github/workflows/hermetic_library_generation.yaml +++ b/.github/workflows/hermetic_library_generation.yaml @@ -43,7 +43,7 @@ jobs: with: fetch-depth: 0 token: ${{ secrets.CLOUD_JAVA_BOT_TOKEN }} - - uses: googleapis/sdk-platform-java/.github/scripts@v2.60.1 + - uses: googleapis/sdk-platform-java/.github/scripts@v2.59.0 if: env.SHOULD_RUN == 'true' with: base_ref: ${{ github.base_ref }} diff --git a/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageClient.java b/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageClient.java index fd884881b..f2a8178d2 100644 --- a/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageClient.java +++ b/gapic-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageClient.java @@ -3096,6 +3096,7 @@ public final ListObjectsPagedResponse listObjects(String parent) { * .setSoftDeleted(true) * .setIncludeFoldersAsPrefixes(true) * .setMatchGlob("matchGlob613636317") + * .setFilter("filter-1274492040") * .build(); * for (Object element : storageClient.listObjects(request).iterateAll()) { * // doThingsWith(element); @@ -3145,6 +3146,7 @@ public final ListObjectsPagedResponse listObjects(ListObjectsRequest request) { * .setSoftDeleted(true) * .setIncludeFoldersAsPrefixes(true) * .setMatchGlob("matchGlob613636317") + * .setFilter("filter-1274492040") * .build(); * ApiFuture future = storageClient.listObjectsPagedCallable().futureCall(request); * // Do something. @@ -3194,6 +3196,7 @@ public final ListObjectsPagedResponse listObjects(ListObjectsRequest request) { * .setSoftDeleted(true) * .setIncludeFoldersAsPrefixes(true) * .setMatchGlob("matchGlob613636317") + * .setFilter("filter-1274492040") * .build(); * while (true) { * ListObjectsResponse response = storageClient.listObjectsCallable().call(request); diff --git a/gapic-google-cloud-storage-v2/src/main/resources/META-INF/native-image/com.google.storage.v2/reflect-config.json b/gapic-google-cloud-storage-v2/src/main/resources/META-INF/native-image/com.google.storage.v2/reflect-config.json index 43d586eeb..547b84669 100644 --- a/gapic-google-cloud-storage-v2/src/main/resources/META-INF/native-image/com.google.storage.v2/reflect-config.json +++ b/gapic-google-cloud-storage-v2/src/main/resources/META-INF/native-image/com.google.storage.v2/reflect-config.json @@ -2636,6 +2636,42 @@ "allDeclaredClasses": true, "allPublicClasses": true }, + { + "name": "com.google.storage.v2.ObjectContexts", + "queryAllDeclaredConstructors": true, + "queryAllPublicConstructors": true, + "queryAllDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + }, + { + "name": "com.google.storage.v2.ObjectContexts$Builder", + "queryAllDeclaredConstructors": true, + "queryAllPublicConstructors": true, + "queryAllDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + }, + { + "name": "com.google.storage.v2.ObjectCustomContextPayload", + "queryAllDeclaredConstructors": true, + "queryAllPublicConstructors": true, + "queryAllDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + }, + { + "name": "com.google.storage.v2.ObjectCustomContextPayload$Builder", + "queryAllDeclaredConstructors": true, + "queryAllPublicConstructors": true, + "queryAllDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + }, { "name": "com.google.storage.v2.ObjectRangeData", "queryAllDeclaredConstructors": true, diff --git a/gapic-google-cloud-storage-v2/src/test/java/com/google/storage/v2/StorageClientTest.java b/gapic-google-cloud-storage-v2/src/test/java/com/google/storage/v2/StorageClientTest.java index cc7a861ba..a19cf6848 100644 --- a/gapic-google-cloud-storage-v2/src/test/java/com/google/storage/v2/StorageClientTest.java +++ b/gapic-google-cloud-storage-v2/src/test/java/com/google/storage/v2/StorageClientTest.java @@ -1041,6 +1041,7 @@ public void composeObjectTest() throws Exception { .setTemporaryHold(true) .setRetentionExpireTime(Timestamp.newBuilder().build()) .putAllMetadata(new HashMap()) + .setContexts(ObjectContexts.newBuilder().build()) .setEventBasedHold(true) .setOwner(Owner.newBuilder().build()) .setCustomerEncryption(CustomerEncryption.newBuilder().build()) @@ -1300,6 +1301,7 @@ public void restoreObjectTest() throws Exception { .setTemporaryHold(true) .setRetentionExpireTime(Timestamp.newBuilder().build()) .putAllMetadata(new HashMap()) + .setContexts(ObjectContexts.newBuilder().build()) .setEventBasedHold(true) .setOwner(Owner.newBuilder().build()) .setCustomerEncryption(CustomerEncryption.newBuilder().build()) @@ -1377,6 +1379,7 @@ public void restoreObjectTest2() throws Exception { .setTemporaryHold(true) .setRetentionExpireTime(Timestamp.newBuilder().build()) .putAllMetadata(new HashMap()) + .setContexts(ObjectContexts.newBuilder().build()) .setEventBasedHold(true) .setOwner(Owner.newBuilder().build()) .setCustomerEncryption(CustomerEncryption.newBuilder().build()) @@ -1491,6 +1494,7 @@ public void getObjectTest() throws Exception { .setTemporaryHold(true) .setRetentionExpireTime(Timestamp.newBuilder().build()) .putAllMetadata(new HashMap()) + .setContexts(ObjectContexts.newBuilder().build()) .setEventBasedHold(true) .setOwner(Owner.newBuilder().build()) .setCustomerEncryption(CustomerEncryption.newBuilder().build()) @@ -1565,6 +1569,7 @@ public void getObjectTest2() throws Exception { .setTemporaryHold(true) .setRetentionExpireTime(Timestamp.newBuilder().build()) .putAllMetadata(new HashMap()) + .setContexts(ObjectContexts.newBuilder().build()) .setEventBasedHold(true) .setOwner(Owner.newBuilder().build()) .setCustomerEncryption(CustomerEncryption.newBuilder().build()) @@ -1639,6 +1644,7 @@ public void getObjectTest3() throws Exception { .setTemporaryHold(true) .setRetentionExpireTime(Timestamp.newBuilder().build()) .putAllMetadata(new HashMap()) + .setContexts(ObjectContexts.newBuilder().build()) .setEventBasedHold(true) .setOwner(Owner.newBuilder().build()) .setCustomerEncryption(CustomerEncryption.newBuilder().build()) @@ -1716,6 +1722,7 @@ public void getObjectTest4() throws Exception { .setTemporaryHold(true) .setRetentionExpireTime(Timestamp.newBuilder().build()) .putAllMetadata(new HashMap()) + .setContexts(ObjectContexts.newBuilder().build()) .setEventBasedHold(true) .setOwner(Owner.newBuilder().build()) .setCustomerEncryption(CustomerEncryption.newBuilder().build()) @@ -1923,6 +1930,7 @@ public void updateObjectTest() throws Exception { .setTemporaryHold(true) .setRetentionExpireTime(Timestamp.newBuilder().build()) .putAllMetadata(new HashMap()) + .setContexts(ObjectContexts.newBuilder().build()) .setEventBasedHold(true) .setOwner(Owner.newBuilder().build()) .setCustomerEncryption(CustomerEncryption.newBuilder().build()) @@ -2425,6 +2433,7 @@ public void moveObjectTest() throws Exception { .setTemporaryHold(true) .setRetentionExpireTime(Timestamp.newBuilder().build()) .putAllMetadata(new HashMap()) + .setContexts(ObjectContexts.newBuilder().build()) .setEventBasedHold(true) .setOwner(Owner.newBuilder().build()) .setCustomerEncryption(CustomerEncryption.newBuilder().build()) @@ -2502,6 +2511,7 @@ public void moveObjectTest2() throws Exception { .setTemporaryHold(true) .setRetentionExpireTime(Timestamp.newBuilder().build()) .putAllMetadata(new HashMap()) + .setContexts(ObjectContexts.newBuilder().build()) .setEventBasedHold(true) .setOwner(Owner.newBuilder().build()) .setCustomerEncryption(CustomerEncryption.newBuilder().build()) diff --git a/generation_config.yaml b/generation_config.yaml index dc5c99754..559faca1f 100644 --- a/generation_config.yaml +++ b/generation_config.yaml @@ -1,5 +1,5 @@ gapic_generator_version: 2.59.0 -googleapis_commitish: cd7fed30706c129f2bca11d5b2ef18f4ad18a7ac +googleapis_commitish: 56f26a7d042d41ca5da9e7cdf16f427c7aee255d libraries_bom_version: 26.61.0 libraries: - api_shortname: storage diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ListObjectsRequest.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ListObjectsRequest.java index e64ea53f1..cec4a76d0 100644 --- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ListObjectsRequest.java +++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ListObjectsRequest.java @@ -47,6 +47,7 @@ private ListObjectsRequest() { lexicographicStart_ = ""; lexicographicEnd_ = ""; matchGlob_ = ""; + filter_ = ""; } @java.lang.Override @@ -637,6 +638,63 @@ public com.google.protobuf.ByteString getMatchGlobBytes() { } } + public static final int FILTER_FIELD_NUMBER = 15; + + @SuppressWarnings("serial") + private volatile java.lang.Object filter_ = ""; + + /** + * + * + *
+   * Optional. Filter the returned objects. Currently only supported for the
+   * `contexts` field. If `delimiter` is set, the returned `prefixes` are exempt
+   * from this filter.
+   * 
+ * + * string filter = 15 [(.google.api.field_behavior) = OPTIONAL]; + * + * @return The filter. + */ + @java.lang.Override + public java.lang.String getFilter() { + java.lang.Object ref = filter_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + filter_ = s; + return s; + } + } + + /** + * + * + *
+   * Optional. Filter the returned objects. Currently only supported for the
+   * `contexts` field. If `delimiter` is set, the returned `prefixes` are exempt
+   * from this filter.
+   * 
+ * + * string filter = 15 [(.google.api.field_behavior) = OPTIONAL]; + * + * @return The bytes for filter. + */ + @java.lang.Override + public com.google.protobuf.ByteString getFilterBytes() { + java.lang.Object ref = filter_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); + filter_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + private byte memoizedIsInitialized = -1; @java.lang.Override @@ -690,6 +748,9 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(matchGlob_)) { com.google.protobuf.GeneratedMessageV3.writeString(output, 14, matchGlob_); } + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(filter_)) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 15, filter_); + } getUnknownFields().writeTo(output); } @@ -738,6 +799,9 @@ public int getSerializedSize() { if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(matchGlob_)) { size += com.google.protobuf.GeneratedMessageV3.computeStringSize(14, matchGlob_); } + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(filter_)) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(15, filter_); + } size += getUnknownFields().getSerializedSize(); memoizedSize = size; return size; @@ -769,6 +833,7 @@ public boolean equals(final java.lang.Object obj) { if (getSoftDeleted() != other.getSoftDeleted()) return false; if (getIncludeFoldersAsPrefixes() != other.getIncludeFoldersAsPrefixes()) return false; if (!getMatchGlob().equals(other.getMatchGlob())) return false; + if (!getFilter().equals(other.getFilter())) return false; if (!getUnknownFields().equals(other.getUnknownFields())) return false; return true; } @@ -808,6 +873,8 @@ public int hashCode() { hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(getIncludeFoldersAsPrefixes()); hash = (37 * hash) + MATCH_GLOB_FIELD_NUMBER; hash = (53 * hash) + getMatchGlob().hashCode(); + hash = (37 * hash) + FILTER_FIELD_NUMBER; + hash = (53 * hash) + getFilter().hashCode(); hash = (29 * hash) + getUnknownFields().hashCode(); memoizedHashCode = hash; return hash; @@ -974,6 +1041,7 @@ public Builder clear() { softDeleted_ = false; includeFoldersAsPrefixes_ = false; matchGlob_ = ""; + filter_ = ""; return this; } @@ -1051,6 +1119,9 @@ private void buildPartial0(com.google.storage.v2.ListObjectsRequest result) { if (((from_bitField0_ & 0x00001000) != 0)) { result.matchGlob_ = matchGlob_; } + if (((from_bitField0_ & 0x00002000) != 0)) { + result.filter_ = filter_; + } result.bitField0_ |= to_bitField0_; } @@ -1152,6 +1223,11 @@ public Builder mergeFrom(com.google.storage.v2.ListObjectsRequest other) { bitField0_ |= 0x00001000; onChanged(); } + if (!other.getFilter().isEmpty()) { + filter_ = other.filter_; + bitField0_ |= 0x00002000; + onChanged(); + } this.mergeUnknownFields(other.getUnknownFields()); onChanged(); return this; @@ -1256,6 +1332,12 @@ public Builder mergeFrom( bitField0_ |= 0x00001000; break; } // case 114 + case 122: + { + filter_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00002000; + break; + } // case 122 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { @@ -2659,6 +2741,127 @@ public Builder setMatchGlobBytes(com.google.protobuf.ByteString value) { return this; } + private java.lang.Object filter_ = ""; + + /** + * + * + *
+     * Optional. Filter the returned objects. Currently only supported for the
+     * `contexts` field. If `delimiter` is set, the returned `prefixes` are exempt
+     * from this filter.
+     * 
+ * + * string filter = 15 [(.google.api.field_behavior) = OPTIONAL]; + * + * @return The filter. + */ + public java.lang.String getFilter() { + java.lang.Object ref = filter_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + filter_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + + /** + * + * + *
+     * Optional. Filter the returned objects. Currently only supported for the
+     * `contexts` field. If `delimiter` is set, the returned `prefixes` are exempt
+     * from this filter.
+     * 
+ * + * string filter = 15 [(.google.api.field_behavior) = OPTIONAL]; + * + * @return The bytes for filter. + */ + public com.google.protobuf.ByteString getFilterBytes() { + java.lang.Object ref = filter_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); + filter_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + /** + * + * + *
+     * Optional. Filter the returned objects. Currently only supported for the
+     * `contexts` field. If `delimiter` is set, the returned `prefixes` are exempt
+     * from this filter.
+     * 
+ * + * string filter = 15 [(.google.api.field_behavior) = OPTIONAL]; + * + * @param value The filter to set. + * @return This builder for chaining. + */ + public Builder setFilter(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + filter_ = value; + bitField0_ |= 0x00002000; + onChanged(); + return this; + } + + /** + * + * + *
+     * Optional. Filter the returned objects. Currently only supported for the
+     * `contexts` field. If `delimiter` is set, the returned `prefixes` are exempt
+     * from this filter.
+     * 
+ * + * string filter = 15 [(.google.api.field_behavior) = OPTIONAL]; + * + * @return This builder for chaining. + */ + public Builder clearFilter() { + filter_ = getDefaultInstance().getFilter(); + bitField0_ = (bitField0_ & ~0x00002000); + onChanged(); + return this; + } + + /** + * + * + *
+     * Optional. Filter the returned objects. Currently only supported for the
+     * `contexts` field. If `delimiter` is set, the returned `prefixes` are exempt
+     * from this filter.
+     * 
+ * + * string filter = 15 [(.google.api.field_behavior) = OPTIONAL]; + * + * @param value The bytes for filter to set. + * @return This builder for chaining. + */ + public Builder setFilterBytes(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + filter_ = value; + bitField0_ |= 0x00002000; + onChanged(); + return this; + } + @java.lang.Override public final Builder setUnknownFields(final com.google.protobuf.UnknownFieldSet unknownFields) { return super.setUnknownFields(unknownFields); diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ListObjectsRequestOrBuilder.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ListObjectsRequestOrBuilder.java index dbf34af3c..3a1ac1905 100644 --- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ListObjectsRequestOrBuilder.java +++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ListObjectsRequestOrBuilder.java @@ -358,4 +358,34 @@ public interface ListObjectsRequestOrBuilder * @return The bytes for matchGlob. */ com.google.protobuf.ByteString getMatchGlobBytes(); + + /** + * + * + *
+   * Optional. Filter the returned objects. Currently only supported for the
+   * `contexts` field. If `delimiter` is set, the returned `prefixes` are exempt
+   * from this filter.
+   * 
+ * + * string filter = 15 [(.google.api.field_behavior) = OPTIONAL]; + * + * @return The filter. + */ + java.lang.String getFilter(); + + /** + * + * + *
+   * Optional. Filter the returned objects. Currently only supported for the
+   * `contexts` field. If `delimiter` is set, the returned `prefixes` are exempt
+   * from this filter.
+   * 
+ * + * string filter = 15 [(.google.api.field_behavior) = OPTIONAL]; + * + * @return The bytes for filter. + */ + com.google.protobuf.ByteString getFilterBytes(); } diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/Object.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/Object.java index ea36d7947..90ccca273 100644 --- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/Object.java +++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/Object.java @@ -2664,6 +2664,71 @@ public java.lang.String getMetadataOrThrow(java.lang.String key) { return map.get(key); } + public static final int CONTEXTS_FIELD_NUMBER = 38; + private com.google.storage.v2.ObjectContexts contexts_; + + /** + * + * + *
+   * Optional. User-defined or system-defined object contexts. Each object
+   * context is a key-payload pair, where the key provides the identification
+   * and the payload holds the associated value and additional metadata.
+   * 
+ * + * + * .google.storage.v2.ObjectContexts contexts = 38 [(.google.api.field_behavior) = OPTIONAL]; + * + * + * @return Whether the contexts field is set. + */ + @java.lang.Override + public boolean hasContexts() { + return ((bitField0_ & 0x00000100) != 0); + } + + /** + * + * + *
+   * Optional. User-defined or system-defined object contexts. Each object
+   * context is a key-payload pair, where the key provides the identification
+   * and the payload holds the associated value and additional metadata.
+   * 
+ * + * + * .google.storage.v2.ObjectContexts contexts = 38 [(.google.api.field_behavior) = OPTIONAL]; + * + * + * @return The contexts. + */ + @java.lang.Override + public com.google.storage.v2.ObjectContexts getContexts() { + return contexts_ == null + ? com.google.storage.v2.ObjectContexts.getDefaultInstance() + : contexts_; + } + + /** + * + * + *
+   * Optional. User-defined or system-defined object contexts. Each object
+   * context is a key-payload pair, where the key provides the identification
+   * and the payload holds the associated value and additional metadata.
+   * 
+ * + * + * .google.storage.v2.ObjectContexts contexts = 38 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + @java.lang.Override + public com.google.storage.v2.ObjectContextsOrBuilder getContextsOrBuilder() { + return contexts_ == null + ? com.google.storage.v2.ObjectContexts.getDefaultInstance() + : contexts_; + } + public static final int EVENT_BASED_HOLD_FIELD_NUMBER = 23; private boolean eventBasedHold_ = false; @@ -2690,7 +2755,7 @@ public java.lang.String getMetadataOrThrow(java.lang.String key) { */ @java.lang.Override public boolean hasEventBasedHold() { - return ((bitField0_ & 0x00000100) != 0); + return ((bitField0_ & 0x00000200) != 0); } /** @@ -2736,7 +2801,7 @@ public boolean getEventBasedHold() { */ @java.lang.Override public boolean hasOwner() { - return ((bitField0_ & 0x00000200) != 0); + return ((bitField0_ & 0x00000400) != 0); } /** @@ -2790,7 +2855,7 @@ public com.google.storage.v2.OwnerOrBuilder getOwnerOrBuilder() { */ @java.lang.Override public boolean hasCustomerEncryption() { - return ((bitField0_ & 0x00000400) != 0); + return ((bitField0_ & 0x00000800) != 0); } /** @@ -2850,7 +2915,7 @@ public com.google.storage.v2.CustomerEncryptionOrBuilder getCustomerEncryptionOr */ @java.lang.Override public boolean hasCustomTime() { - return ((bitField0_ & 0x00000800) != 0); + return ((bitField0_ & 0x00001000) != 0); } /** @@ -2906,7 +2971,7 @@ public com.google.protobuf.TimestampOrBuilder getCustomTimeOrBuilder() { */ @java.lang.Override public boolean hasSoftDeleteTime() { - return ((bitField0_ & 0x00001000) != 0); + return ((bitField0_ & 0x00002000) != 0); } /** @@ -2974,7 +3039,7 @@ public com.google.protobuf.TimestampOrBuilder getSoftDeleteTimeOrBuilder() { */ @java.lang.Override public boolean hasHardDeleteTime() { - return ((bitField0_ & 0x00002000) != 0); + return ((bitField0_ & 0x00004000) != 0); } /** @@ -3040,7 +3105,7 @@ public com.google.protobuf.TimestampOrBuilder getHardDeleteTimeOrBuilder() { */ @java.lang.Override public boolean hasRetention() { - return ((bitField0_ & 0x00004000) != 0); + return ((bitField0_ & 0x00008000) != 0); } /** @@ -3162,28 +3227,28 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io } com.google.protobuf.GeneratedMessageV3.serializeStringMapTo( output, internalGetMetadata(), MetadataDefaultEntryHolder.defaultEntry, 22); - if (((bitField0_ & 0x00000100) != 0)) { + if (((bitField0_ & 0x00000200) != 0)) { output.writeBool(23, eventBasedHold_); } - if (((bitField0_ & 0x00000200) != 0)) { + if (((bitField0_ & 0x00000400) != 0)) { output.writeMessage(24, getOwner()); } - if (((bitField0_ & 0x00000400) != 0)) { + if (((bitField0_ & 0x00000800) != 0)) { output.writeMessage(25, getCustomerEncryption()); } - if (((bitField0_ & 0x00000800) != 0)) { + if (((bitField0_ & 0x00001000) != 0)) { output.writeMessage(26, getCustomTime()); } if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(etag_)) { com.google.protobuf.GeneratedMessageV3.writeString(output, 27, etag_); } - if (((bitField0_ & 0x00001000) != 0)) { + if (((bitField0_ & 0x00002000) != 0)) { output.writeMessage(28, getSoftDeleteTime()); } - if (((bitField0_ & 0x00002000) != 0)) { + if (((bitField0_ & 0x00004000) != 0)) { output.writeMessage(29, getHardDeleteTime()); } - if (((bitField0_ & 0x00004000) != 0)) { + if (((bitField0_ & 0x00008000) != 0)) { output.writeMessage(30, getRetention()); } if (((bitField0_ & 0x00000001) != 0)) { @@ -3192,6 +3257,9 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io if (((bitField0_ & 0x00000004) != 0)) { output.writeMessage(36, getFinalizeTime()); } + if (((bitField0_ & 0x00000100) != 0)) { + output.writeMessage(38, getContexts()); + } getUnknownFields().writeTo(output); } @@ -3276,28 +3344,28 @@ public int getSerializedSize() { .build(); size += com.google.protobuf.CodedOutputStream.computeMessageSize(22, metadata__); } - if (((bitField0_ & 0x00000100) != 0)) { + if (((bitField0_ & 0x00000200) != 0)) { size += com.google.protobuf.CodedOutputStream.computeBoolSize(23, eventBasedHold_); } - if (((bitField0_ & 0x00000200) != 0)) { + if (((bitField0_ & 0x00000400) != 0)) { size += com.google.protobuf.CodedOutputStream.computeMessageSize(24, getOwner()); } - if (((bitField0_ & 0x00000400) != 0)) { + if (((bitField0_ & 0x00000800) != 0)) { size += com.google.protobuf.CodedOutputStream.computeMessageSize(25, getCustomerEncryption()); } - if (((bitField0_ & 0x00000800) != 0)) { + if (((bitField0_ & 0x00001000) != 0)) { size += com.google.protobuf.CodedOutputStream.computeMessageSize(26, getCustomTime()); } if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(etag_)) { size += com.google.protobuf.GeneratedMessageV3.computeStringSize(27, etag_); } - if (((bitField0_ & 0x00001000) != 0)) { + if (((bitField0_ & 0x00002000) != 0)) { size += com.google.protobuf.CodedOutputStream.computeMessageSize(28, getSoftDeleteTime()); } - if (((bitField0_ & 0x00002000) != 0)) { + if (((bitField0_ & 0x00004000) != 0)) { size += com.google.protobuf.CodedOutputStream.computeMessageSize(29, getHardDeleteTime()); } - if (((bitField0_ & 0x00004000) != 0)) { + if (((bitField0_ & 0x00008000) != 0)) { size += com.google.protobuf.CodedOutputStream.computeMessageSize(30, getRetention()); } if (((bitField0_ & 0x00000001) != 0)) { @@ -3306,6 +3374,9 @@ public int getSerializedSize() { if (((bitField0_ & 0x00000004) != 0)) { size += com.google.protobuf.CodedOutputStream.computeMessageSize(36, getFinalizeTime()); } + if (((bitField0_ & 0x00000100) != 0)) { + size += com.google.protobuf.CodedOutputStream.computeMessageSize(38, getContexts()); + } size += getUnknownFields().getSerializedSize(); memoizedSize = size; return size; @@ -3370,6 +3441,10 @@ public boolean equals(final java.lang.Object obj) { if (!getRetentionExpireTime().equals(other.getRetentionExpireTime())) return false; } if (!internalGetMetadata().equals(other.internalGetMetadata())) return false; + if (hasContexts() != other.hasContexts()) return false; + if (hasContexts()) { + if (!getContexts().equals(other.getContexts())) return false; + } if (hasEventBasedHold() != other.hasEventBasedHold()) return false; if (hasEventBasedHold()) { if (getEventBasedHold() != other.getEventBasedHold()) return false; @@ -3479,6 +3554,10 @@ public int hashCode() { hash = (37 * hash) + METADATA_FIELD_NUMBER; hash = (53 * hash) + internalGetMetadata().hashCode(); } + if (hasContexts()) { + hash = (37 * hash) + CONTEXTS_FIELD_NUMBER; + hash = (53 * hash) + getContexts().hashCode(); + } if (hasEventBasedHold()) { hash = (37 * hash) + EVENT_BASED_HOLD_FIELD_NUMBER; hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(getEventBasedHold()); @@ -3675,6 +3754,7 @@ private void maybeForceBuilderInitialization() { getUpdateTimeFieldBuilder(); getUpdateStorageClassTimeFieldBuilder(); getRetentionExpireTimeFieldBuilder(); + getContextsFieldBuilder(); getOwnerFieldBuilder(); getCustomerEncryptionFieldBuilder(); getCustomTimeFieldBuilder(); @@ -3688,6 +3768,7 @@ private void maybeForceBuilderInitialization() { public Builder clear() { super.clear(); bitField0_ = 0; + bitField1_ = 0; name_ = ""; bucket_ = ""; etag_ = ""; @@ -3747,6 +3828,11 @@ public Builder clear() { retentionExpireTimeBuilder_ = null; } internalGetMutableMetadata().clear(); + contexts_ = null; + if (contextsBuilder_ != null) { + contextsBuilder_.dispose(); + contextsBuilder_ = null; + } eventBasedHold_ = false; owner_ = null; if (ownerBuilder_ != null) { @@ -3807,6 +3893,9 @@ public com.google.storage.v2.Object buildPartial() { if (bitField0_ != 0) { buildPartial0(result); } + if (bitField1_ != 0) { + buildPartial1(result); + } onBuilt(); return result; } @@ -3915,41 +4004,51 @@ private void buildPartial0(com.google.storage.v2.Object result) { result.metadata_.makeImmutable(); } if (((from_bitField0_ & 0x02000000) != 0)) { - result.eventBasedHold_ = eventBasedHold_; + result.contexts_ = contextsBuilder_ == null ? contexts_ : contextsBuilder_.build(); to_bitField0_ |= 0x00000100; } if (((from_bitField0_ & 0x04000000) != 0)) { - result.owner_ = ownerBuilder_ == null ? owner_ : ownerBuilder_.build(); + result.eventBasedHold_ = eventBasedHold_; to_bitField0_ |= 0x00000200; } if (((from_bitField0_ & 0x08000000) != 0)) { + result.owner_ = ownerBuilder_ == null ? owner_ : ownerBuilder_.build(); + to_bitField0_ |= 0x00000400; + } + if (((from_bitField0_ & 0x10000000) != 0)) { result.customerEncryption_ = customerEncryptionBuilder_ == null ? customerEncryption_ : customerEncryptionBuilder_.build(); - to_bitField0_ |= 0x00000400; - } - if (((from_bitField0_ & 0x10000000) != 0)) { - result.customTime_ = customTimeBuilder_ == null ? customTime_ : customTimeBuilder_.build(); to_bitField0_ |= 0x00000800; } if (((from_bitField0_ & 0x20000000) != 0)) { - result.softDeleteTime_ = - softDeleteTimeBuilder_ == null ? softDeleteTime_ : softDeleteTimeBuilder_.build(); + result.customTime_ = customTimeBuilder_ == null ? customTime_ : customTimeBuilder_.build(); to_bitField0_ |= 0x00001000; } if (((from_bitField0_ & 0x40000000) != 0)) { - result.hardDeleteTime_ = - hardDeleteTimeBuilder_ == null ? hardDeleteTime_ : hardDeleteTimeBuilder_.build(); + result.softDeleteTime_ = + softDeleteTimeBuilder_ == null ? softDeleteTime_ : softDeleteTimeBuilder_.build(); to_bitField0_ |= 0x00002000; } if (((from_bitField0_ & 0x80000000) != 0)) { - result.retention_ = retentionBuilder_ == null ? retention_ : retentionBuilder_.build(); + result.hardDeleteTime_ = + hardDeleteTimeBuilder_ == null ? hardDeleteTime_ : hardDeleteTimeBuilder_.build(); to_bitField0_ |= 0x00004000; } result.bitField0_ |= to_bitField0_; } + private void buildPartial1(com.google.storage.v2.Object result) { + int from_bitField1_ = bitField1_; + int to_bitField0_ = 0; + if (((from_bitField1_ & 0x00000001) != 0)) { + result.retention_ = retentionBuilder_ == null ? retention_ : retentionBuilder_.build(); + to_bitField0_ |= 0x00008000; + } + result.bitField0_ |= to_bitField0_; + } + @java.lang.Override public Builder clone() { return super.clone(); @@ -4115,6 +4214,9 @@ public Builder mergeFrom(com.google.storage.v2.Object other) { } internalGetMutableMetadata().mergeFrom(other.internalGetMetadata()); bitField0_ |= 0x01000000; + if (other.hasContexts()) { + mergeContexts(other.getContexts()); + } if (other.hasEventBasedHold()) { setEventBasedHold(other.getEventBasedHold()); } @@ -4312,26 +4414,26 @@ public Builder mergeFrom( case 184: { eventBasedHold_ = input.readBool(); - bitField0_ |= 0x02000000; + bitField0_ |= 0x04000000; break; } // case 184 case 194: { input.readMessage(getOwnerFieldBuilder().getBuilder(), extensionRegistry); - bitField0_ |= 0x04000000; + bitField0_ |= 0x08000000; break; } // case 194 case 202: { input.readMessage( getCustomerEncryptionFieldBuilder().getBuilder(), extensionRegistry); - bitField0_ |= 0x08000000; + bitField0_ |= 0x10000000; break; } // case 202 case 210: { input.readMessage(getCustomTimeFieldBuilder().getBuilder(), extensionRegistry); - bitField0_ |= 0x10000000; + bitField0_ |= 0x20000000; break; } // case 210 case 218: @@ -4343,19 +4445,19 @@ public Builder mergeFrom( case 226: { input.readMessage(getSoftDeleteTimeFieldBuilder().getBuilder(), extensionRegistry); - bitField0_ |= 0x20000000; + bitField0_ |= 0x40000000; break; } // case 226 case 234: { input.readMessage(getHardDeleteTimeFieldBuilder().getBuilder(), extensionRegistry); - bitField0_ |= 0x40000000; + bitField0_ |= 0x80000000; break; } // case 234 case 242: { input.readMessage(getRetentionFieldBuilder().getBuilder(), extensionRegistry); - bitField0_ |= 0x80000000; + bitField1_ |= 0x00000001; break; } // case 242 case 282: @@ -4370,6 +4472,12 @@ public Builder mergeFrom( bitField0_ |= 0x00004000; break; } // case 290 + case 306: + { + input.readMessage(getContextsFieldBuilder().getBuilder(), extensionRegistry); + bitField0_ |= 0x02000000; + break; + } // case 306 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { @@ -4388,6 +4496,7 @@ public Builder mergeFrom( } private int bitField0_; + private int bitField1_; private java.lang.Object name_ = ""; @@ -8311,6 +8420,236 @@ public Builder putAllMetadata(java.util.Map return this; } + private com.google.storage.v2.ObjectContexts contexts_; + private com.google.protobuf.SingleFieldBuilderV3< + com.google.storage.v2.ObjectContexts, + com.google.storage.v2.ObjectContexts.Builder, + com.google.storage.v2.ObjectContextsOrBuilder> + contextsBuilder_; + + /** + * + * + *
+     * Optional. User-defined or system-defined object contexts. Each object
+     * context is a key-payload pair, where the key provides the identification
+     * and the payload holds the associated value and additional metadata.
+     * 
+ * + * + * .google.storage.v2.ObjectContexts contexts = 38 [(.google.api.field_behavior) = OPTIONAL]; + * + * + * @return Whether the contexts field is set. + */ + public boolean hasContexts() { + return ((bitField0_ & 0x02000000) != 0); + } + + /** + * + * + *
+     * Optional. User-defined or system-defined object contexts. Each object
+     * context is a key-payload pair, where the key provides the identification
+     * and the payload holds the associated value and additional metadata.
+     * 
+ * + * + * .google.storage.v2.ObjectContexts contexts = 38 [(.google.api.field_behavior) = OPTIONAL]; + * + * + * @return The contexts. + */ + public com.google.storage.v2.ObjectContexts getContexts() { + if (contextsBuilder_ == null) { + return contexts_ == null + ? com.google.storage.v2.ObjectContexts.getDefaultInstance() + : contexts_; + } else { + return contextsBuilder_.getMessage(); + } + } + + /** + * + * + *
+     * Optional. User-defined or system-defined object contexts. Each object
+     * context is a key-payload pair, where the key provides the identification
+     * and the payload holds the associated value and additional metadata.
+     * 
+ * + * + * .google.storage.v2.ObjectContexts contexts = 38 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + public Builder setContexts(com.google.storage.v2.ObjectContexts value) { + if (contextsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + contexts_ = value; + } else { + contextsBuilder_.setMessage(value); + } + bitField0_ |= 0x02000000; + onChanged(); + return this; + } + + /** + * + * + *
+     * Optional. User-defined or system-defined object contexts. Each object
+     * context is a key-payload pair, where the key provides the identification
+     * and the payload holds the associated value and additional metadata.
+     * 
+ * + * + * .google.storage.v2.ObjectContexts contexts = 38 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + public Builder setContexts(com.google.storage.v2.ObjectContexts.Builder builderForValue) { + if (contextsBuilder_ == null) { + contexts_ = builderForValue.build(); + } else { + contextsBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x02000000; + onChanged(); + return this; + } + + /** + * + * + *
+     * Optional. User-defined or system-defined object contexts. Each object
+     * context is a key-payload pair, where the key provides the identification
+     * and the payload holds the associated value and additional metadata.
+     * 
+ * + * + * .google.storage.v2.ObjectContexts contexts = 38 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + public Builder mergeContexts(com.google.storage.v2.ObjectContexts value) { + if (contextsBuilder_ == null) { + if (((bitField0_ & 0x02000000) != 0) + && contexts_ != null + && contexts_ != com.google.storage.v2.ObjectContexts.getDefaultInstance()) { + getContextsBuilder().mergeFrom(value); + } else { + contexts_ = value; + } + } else { + contextsBuilder_.mergeFrom(value); + } + if (contexts_ != null) { + bitField0_ |= 0x02000000; + onChanged(); + } + return this; + } + + /** + * + * + *
+     * Optional. User-defined or system-defined object contexts. Each object
+     * context is a key-payload pair, where the key provides the identification
+     * and the payload holds the associated value and additional metadata.
+     * 
+ * + * + * .google.storage.v2.ObjectContexts contexts = 38 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + public Builder clearContexts() { + bitField0_ = (bitField0_ & ~0x02000000); + contexts_ = null; + if (contextsBuilder_ != null) { + contextsBuilder_.dispose(); + contextsBuilder_ = null; + } + onChanged(); + return this; + } + + /** + * + * + *
+     * Optional. User-defined or system-defined object contexts. Each object
+     * context is a key-payload pair, where the key provides the identification
+     * and the payload holds the associated value and additional metadata.
+     * 
+ * + * + * .google.storage.v2.ObjectContexts contexts = 38 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + public com.google.storage.v2.ObjectContexts.Builder getContextsBuilder() { + bitField0_ |= 0x02000000; + onChanged(); + return getContextsFieldBuilder().getBuilder(); + } + + /** + * + * + *
+     * Optional. User-defined or system-defined object contexts. Each object
+     * context is a key-payload pair, where the key provides the identification
+     * and the payload holds the associated value and additional metadata.
+     * 
+ * + * + * .google.storage.v2.ObjectContexts contexts = 38 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + public com.google.storage.v2.ObjectContextsOrBuilder getContextsOrBuilder() { + if (contextsBuilder_ != null) { + return contextsBuilder_.getMessageOrBuilder(); + } else { + return contexts_ == null + ? com.google.storage.v2.ObjectContexts.getDefaultInstance() + : contexts_; + } + } + + /** + * + * + *
+     * Optional. User-defined or system-defined object contexts. Each object
+     * context is a key-payload pair, where the key provides the identification
+     * and the payload holds the associated value and additional metadata.
+     * 
+ * + * + * .google.storage.v2.ObjectContexts contexts = 38 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + private com.google.protobuf.SingleFieldBuilderV3< + com.google.storage.v2.ObjectContexts, + com.google.storage.v2.ObjectContexts.Builder, + com.google.storage.v2.ObjectContextsOrBuilder> + getContextsFieldBuilder() { + if (contextsBuilder_ == null) { + contextsBuilder_ = + new com.google.protobuf.SingleFieldBuilderV3< + com.google.storage.v2.ObjectContexts, + com.google.storage.v2.ObjectContexts.Builder, + com.google.storage.v2.ObjectContextsOrBuilder>( + getContexts(), getParentForChildren(), isClean()); + contexts_ = null; + } + return contextsBuilder_; + } + private boolean eventBasedHold_; /** @@ -8336,7 +8675,7 @@ public Builder putAllMetadata(java.util.Map */ @java.lang.Override public boolean hasEventBasedHold() { - return ((bitField0_ & 0x02000000) != 0); + return ((bitField0_ & 0x04000000) != 0); } /** @@ -8390,7 +8729,7 @@ public boolean getEventBasedHold() { public Builder setEventBasedHold(boolean value) { eventBasedHold_ = value; - bitField0_ |= 0x02000000; + bitField0_ |= 0x04000000; onChanged(); return this; } @@ -8417,7 +8756,7 @@ public Builder setEventBasedHold(boolean value) { * @return This builder for chaining. */ public Builder clearEventBasedHold() { - bitField0_ = (bitField0_ & ~0x02000000); + bitField0_ = (bitField0_ & ~0x04000000); eventBasedHold_ = false; onChanged(); return this; @@ -8444,7 +8783,7 @@ public Builder clearEventBasedHold() { * @return Whether the owner field is set. */ public boolean hasOwner() { - return ((bitField0_ & 0x04000000) != 0); + return ((bitField0_ & 0x08000000) != 0); } /** @@ -8488,7 +8827,7 @@ public Builder setOwner(com.google.storage.v2.Owner value) { } else { ownerBuilder_.setMessage(value); } - bitField0_ |= 0x04000000; + bitField0_ |= 0x08000000; onChanged(); return this; } @@ -8510,7 +8849,7 @@ public Builder setOwner(com.google.storage.v2.Owner.Builder builderForValue) { } else { ownerBuilder_.setMessage(builderForValue.build()); } - bitField0_ |= 0x04000000; + bitField0_ |= 0x08000000; onChanged(); return this; } @@ -8528,7 +8867,7 @@ public Builder setOwner(com.google.storage.v2.Owner.Builder builderForValue) { */ public Builder mergeOwner(com.google.storage.v2.Owner value) { if (ownerBuilder_ == null) { - if (((bitField0_ & 0x04000000) != 0) + if (((bitField0_ & 0x08000000) != 0) && owner_ != null && owner_ != com.google.storage.v2.Owner.getDefaultInstance()) { getOwnerBuilder().mergeFrom(value); @@ -8539,7 +8878,7 @@ public Builder mergeOwner(com.google.storage.v2.Owner value) { ownerBuilder_.mergeFrom(value); } if (owner_ != null) { - bitField0_ |= 0x04000000; + bitField0_ |= 0x08000000; onChanged(); } return this; @@ -8557,7 +8896,7 @@ public Builder mergeOwner(com.google.storage.v2.Owner value) { * */ public Builder clearOwner() { - bitField0_ = (bitField0_ & ~0x04000000); + bitField0_ = (bitField0_ & ~0x08000000); owner_ = null; if (ownerBuilder_ != null) { ownerBuilder_.dispose(); @@ -8579,7 +8918,7 @@ public Builder clearOwner() { * */ public com.google.storage.v2.Owner.Builder getOwnerBuilder() { - bitField0_ |= 0x04000000; + bitField0_ |= 0x08000000; onChanged(); return getOwnerFieldBuilder().getBuilder(); } @@ -8653,7 +8992,7 @@ public com.google.storage.v2.OwnerOrBuilder getOwnerOrBuilder() { * @return Whether the customerEncryption field is set. */ public boolean hasCustomerEncryption() { - return ((bitField0_ & 0x08000000) != 0); + return ((bitField0_ & 0x10000000) != 0); } /** @@ -8701,7 +9040,7 @@ public Builder setCustomerEncryption(com.google.storage.v2.CustomerEncryption va } else { customerEncryptionBuilder_.setMessage(value); } - bitField0_ |= 0x08000000; + bitField0_ |= 0x10000000; onChanged(); return this; } @@ -8725,7 +9064,7 @@ public Builder setCustomerEncryption( } else { customerEncryptionBuilder_.setMessage(builderForValue.build()); } - bitField0_ |= 0x08000000; + bitField0_ |= 0x10000000; onChanged(); return this; } @@ -8744,7 +9083,7 @@ public Builder setCustomerEncryption( */ public Builder mergeCustomerEncryption(com.google.storage.v2.CustomerEncryption value) { if (customerEncryptionBuilder_ == null) { - if (((bitField0_ & 0x08000000) != 0) + if (((bitField0_ & 0x10000000) != 0) && customerEncryption_ != null && customerEncryption_ != com.google.storage.v2.CustomerEncryption.getDefaultInstance()) { @@ -8756,7 +9095,7 @@ public Builder mergeCustomerEncryption(com.google.storage.v2.CustomerEncryption customerEncryptionBuilder_.mergeFrom(value); } if (customerEncryption_ != null) { - bitField0_ |= 0x08000000; + bitField0_ |= 0x10000000; onChanged(); } return this; @@ -8775,7 +9114,7 @@ public Builder mergeCustomerEncryption(com.google.storage.v2.CustomerEncryption * */ public Builder clearCustomerEncryption() { - bitField0_ = (bitField0_ & ~0x08000000); + bitField0_ = (bitField0_ & ~0x10000000); customerEncryption_ = null; if (customerEncryptionBuilder_ != null) { customerEncryptionBuilder_.dispose(); @@ -8798,7 +9137,7 @@ public Builder clearCustomerEncryption() { * */ public com.google.storage.v2.CustomerEncryption.Builder getCustomerEncryptionBuilder() { - bitField0_ |= 0x08000000; + bitField0_ |= 0x10000000; onChanged(); return getCustomerEncryptionFieldBuilder().getBuilder(); } @@ -8874,7 +9213,7 @@ public com.google.storage.v2.CustomerEncryptionOrBuilder getCustomerEncryptionOr * @return Whether the customTime field is set. */ public boolean hasCustomTime() { - return ((bitField0_ & 0x10000000) != 0); + return ((bitField0_ & 0x20000000) != 0); } /** @@ -8918,7 +9257,7 @@ public Builder setCustomTime(com.google.protobuf.Timestamp value) { } else { customTimeBuilder_.setMessage(value); } - bitField0_ |= 0x10000000; + bitField0_ |= 0x20000000; onChanged(); return this; } @@ -8939,7 +9278,7 @@ public Builder setCustomTime(com.google.protobuf.Timestamp.Builder builderForVal } else { customTimeBuilder_.setMessage(builderForValue.build()); } - bitField0_ |= 0x10000000; + bitField0_ |= 0x20000000; onChanged(); return this; } @@ -8956,7 +9295,7 @@ public Builder setCustomTime(com.google.protobuf.Timestamp.Builder builderForVal */ public Builder mergeCustomTime(com.google.protobuf.Timestamp value) { if (customTimeBuilder_ == null) { - if (((bitField0_ & 0x10000000) != 0) + if (((bitField0_ & 0x20000000) != 0) && customTime_ != null && customTime_ != com.google.protobuf.Timestamp.getDefaultInstance()) { getCustomTimeBuilder().mergeFrom(value); @@ -8967,7 +9306,7 @@ public Builder mergeCustomTime(com.google.protobuf.Timestamp value) { customTimeBuilder_.mergeFrom(value); } if (customTime_ != null) { - bitField0_ |= 0x10000000; + bitField0_ |= 0x20000000; onChanged(); } return this; @@ -8984,7 +9323,7 @@ public Builder mergeCustomTime(com.google.protobuf.Timestamp value) { * */ public Builder clearCustomTime() { - bitField0_ = (bitField0_ & ~0x10000000); + bitField0_ = (bitField0_ & ~0x20000000); customTime_ = null; if (customTimeBuilder_ != null) { customTimeBuilder_.dispose(); @@ -9005,7 +9344,7 @@ public Builder clearCustomTime() { * */ public com.google.protobuf.Timestamp.Builder getCustomTimeBuilder() { - bitField0_ |= 0x10000000; + bitField0_ |= 0x20000000; onChanged(); return getCustomTimeFieldBuilder().getBuilder(); } @@ -9081,7 +9420,7 @@ public com.google.protobuf.TimestampOrBuilder getCustomTimeOrBuilder() { * @return Whether the softDeleteTime field is set. */ public boolean hasSoftDeleteTime() { - return ((bitField0_ & 0x20000000) != 0); + return ((bitField0_ & 0x40000000) != 0); } /** @@ -9133,7 +9472,7 @@ public Builder setSoftDeleteTime(com.google.protobuf.Timestamp value) { } else { softDeleteTimeBuilder_.setMessage(value); } - bitField0_ |= 0x20000000; + bitField0_ |= 0x40000000; onChanged(); return this; } @@ -9158,7 +9497,7 @@ public Builder setSoftDeleteTime(com.google.protobuf.Timestamp.Builder builderFo } else { softDeleteTimeBuilder_.setMessage(builderForValue.build()); } - bitField0_ |= 0x20000000; + bitField0_ |= 0x40000000; onChanged(); return this; } @@ -9179,7 +9518,7 @@ public Builder setSoftDeleteTime(com.google.protobuf.Timestamp.Builder builderFo */ public Builder mergeSoftDeleteTime(com.google.protobuf.Timestamp value) { if (softDeleteTimeBuilder_ == null) { - if (((bitField0_ & 0x20000000) != 0) + if (((bitField0_ & 0x40000000) != 0) && softDeleteTime_ != null && softDeleteTime_ != com.google.protobuf.Timestamp.getDefaultInstance()) { getSoftDeleteTimeBuilder().mergeFrom(value); @@ -9190,7 +9529,7 @@ public Builder mergeSoftDeleteTime(com.google.protobuf.Timestamp value) { softDeleteTimeBuilder_.mergeFrom(value); } if (softDeleteTime_ != null) { - bitField0_ |= 0x20000000; + bitField0_ |= 0x40000000; onChanged(); } return this; @@ -9211,7 +9550,7 @@ public Builder mergeSoftDeleteTime(com.google.protobuf.Timestamp value) { * */ public Builder clearSoftDeleteTime() { - bitField0_ = (bitField0_ & ~0x20000000); + bitField0_ = (bitField0_ & ~0x40000000); softDeleteTime_ = null; if (softDeleteTimeBuilder_ != null) { softDeleteTimeBuilder_.dispose(); @@ -9236,7 +9575,7 @@ public Builder clearSoftDeleteTime() { * */ public com.google.protobuf.Timestamp.Builder getSoftDeleteTimeBuilder() { - bitField0_ |= 0x20000000; + bitField0_ |= 0x40000000; onChanged(); return getSoftDeleteTimeFieldBuilder().getBuilder(); } @@ -9320,7 +9659,7 @@ public com.google.protobuf.TimestampOrBuilder getSoftDeleteTimeOrBuilder() { * @return Whether the hardDeleteTime field is set. */ public boolean hasHardDeleteTime() { - return ((bitField0_ & 0x40000000) != 0); + return ((bitField0_ & 0x80000000) != 0); } /** @@ -9372,7 +9711,7 @@ public Builder setHardDeleteTime(com.google.protobuf.Timestamp value) { } else { hardDeleteTimeBuilder_.setMessage(value); } - bitField0_ |= 0x40000000; + bitField0_ |= 0x80000000; onChanged(); return this; } @@ -9397,7 +9736,7 @@ public Builder setHardDeleteTime(com.google.protobuf.Timestamp.Builder builderFo } else { hardDeleteTimeBuilder_.setMessage(builderForValue.build()); } - bitField0_ |= 0x40000000; + bitField0_ |= 0x80000000; onChanged(); return this; } @@ -9418,7 +9757,7 @@ public Builder setHardDeleteTime(com.google.protobuf.Timestamp.Builder builderFo */ public Builder mergeHardDeleteTime(com.google.protobuf.Timestamp value) { if (hardDeleteTimeBuilder_ == null) { - if (((bitField0_ & 0x40000000) != 0) + if (((bitField0_ & 0x80000000) != 0) && hardDeleteTime_ != null && hardDeleteTime_ != com.google.protobuf.Timestamp.getDefaultInstance()) { getHardDeleteTimeBuilder().mergeFrom(value); @@ -9429,7 +9768,7 @@ public Builder mergeHardDeleteTime(com.google.protobuf.Timestamp value) { hardDeleteTimeBuilder_.mergeFrom(value); } if (hardDeleteTime_ != null) { - bitField0_ |= 0x40000000; + bitField0_ |= 0x80000000; onChanged(); } return this; @@ -9450,7 +9789,7 @@ public Builder mergeHardDeleteTime(com.google.protobuf.Timestamp value) { * */ public Builder clearHardDeleteTime() { - bitField0_ = (bitField0_ & ~0x40000000); + bitField0_ = (bitField0_ & ~0x80000000); hardDeleteTime_ = null; if (hardDeleteTimeBuilder_ != null) { hardDeleteTimeBuilder_.dispose(); @@ -9475,7 +9814,7 @@ public Builder clearHardDeleteTime() { * */ public com.google.protobuf.Timestamp.Builder getHardDeleteTimeBuilder() { - bitField0_ |= 0x40000000; + bitField0_ |= 0x80000000; onChanged(); return getHardDeleteTimeFieldBuilder().getBuilder(); } @@ -9557,7 +9896,7 @@ public com.google.protobuf.TimestampOrBuilder getHardDeleteTimeOrBuilder() { * @return Whether the retention field is set. */ public boolean hasRetention() { - return ((bitField0_ & 0x80000000) != 0); + return ((bitField1_ & 0x00000001) != 0); } /** @@ -9605,7 +9944,7 @@ public Builder setRetention(com.google.storage.v2.Object.Retention value) { } else { retentionBuilder_.setMessage(value); } - bitField0_ |= 0x80000000; + bitField1_ |= 0x00000001; onChanged(); return this; } @@ -9628,7 +9967,7 @@ public Builder setRetention(com.google.storage.v2.Object.Retention.Builder build } else { retentionBuilder_.setMessage(builderForValue.build()); } - bitField0_ |= 0x80000000; + bitField1_ |= 0x00000001; onChanged(); return this; } @@ -9647,7 +9986,7 @@ public Builder setRetention(com.google.storage.v2.Object.Retention.Builder build */ public Builder mergeRetention(com.google.storage.v2.Object.Retention value) { if (retentionBuilder_ == null) { - if (((bitField0_ & 0x80000000) != 0) + if (((bitField1_ & 0x00000001) != 0) && retention_ != null && retention_ != com.google.storage.v2.Object.Retention.getDefaultInstance()) { getRetentionBuilder().mergeFrom(value); @@ -9658,7 +9997,7 @@ public Builder mergeRetention(com.google.storage.v2.Object.Retention value) { retentionBuilder_.mergeFrom(value); } if (retention_ != null) { - bitField0_ |= 0x80000000; + bitField1_ |= 0x00000001; onChanged(); } return this; @@ -9677,7 +10016,7 @@ public Builder mergeRetention(com.google.storage.v2.Object.Retention value) { * */ public Builder clearRetention() { - bitField0_ = (bitField0_ & ~0x80000000); + bitField1_ = (bitField1_ & ~0x00000001); retention_ = null; if (retentionBuilder_ != null) { retentionBuilder_.dispose(); @@ -9700,7 +10039,7 @@ public Builder clearRetention() { * */ public com.google.storage.v2.Object.Retention.Builder getRetentionBuilder() { - bitField0_ |= 0x80000000; + bitField1_ |= 0x00000001; onChanged(); return getRetentionFieldBuilder().getBuilder(); } diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectContexts.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectContexts.java new file mode 100644 index 000000000..bfa57fdc5 --- /dev/null +++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectContexts.java @@ -0,0 +1,902 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/storage/v2/storage.proto + +// Protobuf Java Version: 3.25.8 +package com.google.storage.v2; + +/** + * + * + *
+ * All contexts of an object grouped by type.
+ * 
+ * + * Protobuf type {@code google.storage.v2.ObjectContexts} + */ +public final class ObjectContexts extends com.google.protobuf.GeneratedMessageV3 + implements + // @@protoc_insertion_point(message_implements:google.storage.v2.ObjectContexts) + ObjectContextsOrBuilder { + private static final long serialVersionUID = 0L; + + // Use ObjectContexts.newBuilder() to construct. + private ObjectContexts(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + + private ObjectContexts() {} + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance(UnusedPrivateParameter unused) { + return new ObjectContexts(); + } + + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { + return com.google.storage.v2.StorageProto + .internal_static_google_storage_v2_ObjectContexts_descriptor; + } + + @SuppressWarnings({"rawtypes"}) + @java.lang.Override + protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( + int number) { + switch (number) { + case 1: + return internalGetCustom(); + default: + throw new RuntimeException("Invalid map field number: " + number); + } + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.google.storage.v2.StorageProto + .internal_static_google_storage_v2_ObjectContexts_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.google.storage.v2.ObjectContexts.class, + com.google.storage.v2.ObjectContexts.Builder.class); + } + + public static final int CUSTOM_FIELD_NUMBER = 1; + + private static final class CustomDefaultEntryHolder { + static final com.google.protobuf.MapEntry< + java.lang.String, com.google.storage.v2.ObjectCustomContextPayload> + defaultEntry = + com.google.protobuf.MapEntry + . + newDefaultInstance( + com.google.storage.v2.StorageProto + .internal_static_google_storage_v2_ObjectContexts_CustomEntry_descriptor, + com.google.protobuf.WireFormat.FieldType.STRING, + "", + com.google.protobuf.WireFormat.FieldType.MESSAGE, + com.google.storage.v2.ObjectCustomContextPayload.getDefaultInstance()); + } + + @SuppressWarnings("serial") + private com.google.protobuf.MapField< + java.lang.String, com.google.storage.v2.ObjectCustomContextPayload> + custom_; + + private com.google.protobuf.MapField< + java.lang.String, com.google.storage.v2.ObjectCustomContextPayload> + internalGetCustom() { + if (custom_ == null) { + return com.google.protobuf.MapField.emptyMapField(CustomDefaultEntryHolder.defaultEntry); + } + return custom_; + } + + public int getCustomCount() { + return internalGetCustom().getMap().size(); + } + + /** + * + * + *
+   * Optional. User-defined object contexts.
+   * 
+ * + * + * map<string, .google.storage.v2.ObjectCustomContextPayload> custom = 1 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + @java.lang.Override + public boolean containsCustom(java.lang.String key) { + if (key == null) { + throw new NullPointerException("map key"); + } + return internalGetCustom().getMap().containsKey(key); + } + + /** Use {@link #getCustomMap()} instead. */ + @java.lang.Override + @java.lang.Deprecated + public java.util.Map + getCustom() { + return getCustomMap(); + } + + /** + * + * + *
+   * Optional. User-defined object contexts.
+   * 
+ * + * + * map<string, .google.storage.v2.ObjectCustomContextPayload> custom = 1 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + @java.lang.Override + public java.util.Map + getCustomMap() { + return internalGetCustom().getMap(); + } + + /** + * + * + *
+   * Optional. User-defined object contexts.
+   * 
+ * + * + * map<string, .google.storage.v2.ObjectCustomContextPayload> custom = 1 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + @java.lang.Override + public /* nullable */ com.google.storage.v2.ObjectCustomContextPayload getCustomOrDefault( + java.lang.String key, + /* nullable */ + com.google.storage.v2.ObjectCustomContextPayload defaultValue) { + if (key == null) { + throw new NullPointerException("map key"); + } + java.util.Map map = + internalGetCustom().getMap(); + return map.containsKey(key) ? map.get(key) : defaultValue; + } + + /** + * + * + *
+   * Optional. User-defined object contexts.
+   * 
+ * + * + * map<string, .google.storage.v2.ObjectCustomContextPayload> custom = 1 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + @java.lang.Override + public com.google.storage.v2.ObjectCustomContextPayload getCustomOrThrow(java.lang.String key) { + if (key == null) { + throw new NullPointerException("map key"); + } + java.util.Map map = + internalGetCustom().getMap(); + if (!map.containsKey(key)) { + throw new java.lang.IllegalArgumentException(); + } + return map.get(key); + } + + private byte memoizedIsInitialized = -1; + + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { + com.google.protobuf.GeneratedMessageV3.serializeStringMapTo( + output, internalGetCustom(), CustomDefaultEntryHolder.defaultEntry, 1); + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + for (java.util.Map.Entry + entry : internalGetCustom().getMap().entrySet()) { + com.google.protobuf.MapEntry< + java.lang.String, com.google.storage.v2.ObjectCustomContextPayload> + custom__ = + CustomDefaultEntryHolder.defaultEntry + .newBuilderForType() + .setKey(entry.getKey()) + .setValue(entry.getValue()) + .build(); + size += com.google.protobuf.CodedOutputStream.computeMessageSize(1, custom__); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof com.google.storage.v2.ObjectContexts)) { + return super.equals(obj); + } + com.google.storage.v2.ObjectContexts other = (com.google.storage.v2.ObjectContexts) obj; + + if (!internalGetCustom().equals(other.internalGetCustom())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + if (!internalGetCustom().getMap().isEmpty()) { + hash = (37 * hash) + CUSTOM_FIELD_NUMBER; + hash = (53 * hash) + internalGetCustom().hashCode(); + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static com.google.storage.v2.ObjectContexts parseFrom(java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static com.google.storage.v2.ObjectContexts parseFrom( + java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static com.google.storage.v2.ObjectContexts parseFrom(com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static com.google.storage.v2.ObjectContexts parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static com.google.storage.v2.ObjectContexts parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static com.google.storage.v2.ObjectContexts parseFrom( + byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static com.google.storage.v2.ObjectContexts parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input); + } + + public static com.google.storage.v2.ObjectContexts parseFrom( + java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseWithIOException( + PARSER, input, extensionRegistry); + } + + public static com.google.storage.v2.ObjectContexts parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException(PARSER, input); + } + + public static com.google.storage.v2.ObjectContexts parseDelimitedFrom( + java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException( + PARSER, input, extensionRegistry); + } + + public static com.google.storage.v2.ObjectContexts parseFrom( + com.google.protobuf.CodedInputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input); + } + + public static com.google.storage.v2.ObjectContexts parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseWithIOException( + PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { + return newBuilder(); + } + + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + + public static Builder newBuilder(com.google.storage.v2.ObjectContexts prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType(com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + + /** + * + * + *
+   * All contexts of an object grouped by type.
+   * 
+ * + * Protobuf type {@code google.storage.v2.ObjectContexts} + */ + public static final class Builder extends com.google.protobuf.GeneratedMessageV3.Builder + implements + // @@protoc_insertion_point(builder_implements:google.storage.v2.ObjectContexts) + com.google.storage.v2.ObjectContextsOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { + return com.google.storage.v2.StorageProto + .internal_static_google_storage_v2_ObjectContexts_descriptor; + } + + @SuppressWarnings({"rawtypes"}) + protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( + int number) { + switch (number) { + case 1: + return internalGetCustom(); + default: + throw new RuntimeException("Invalid map field number: " + number); + } + } + + @SuppressWarnings({"rawtypes"}) + protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFieldReflection( + int number) { + switch (number) { + case 1: + return internalGetMutableCustom(); + default: + throw new RuntimeException("Invalid map field number: " + number); + } + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.google.storage.v2.StorageProto + .internal_static_google_storage_v2_ObjectContexts_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.google.storage.v2.ObjectContexts.class, + com.google.storage.v2.ObjectContexts.Builder.class); + } + + // Construct using com.google.storage.v2.ObjectContexts.newBuilder() + private Builder() {} + + private Builder(com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + super(parent); + } + + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + internalGetMutableCustom().clear(); + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { + return com.google.storage.v2.StorageProto + .internal_static_google_storage_v2_ObjectContexts_descriptor; + } + + @java.lang.Override + public com.google.storage.v2.ObjectContexts getDefaultInstanceForType() { + return com.google.storage.v2.ObjectContexts.getDefaultInstance(); + } + + @java.lang.Override + public com.google.storage.v2.ObjectContexts build() { + com.google.storage.v2.ObjectContexts result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public com.google.storage.v2.ObjectContexts buildPartial() { + com.google.storage.v2.ObjectContexts result = new com.google.storage.v2.ObjectContexts(this); + if (bitField0_ != 0) { + buildPartial0(result); + } + onBuilt(); + return result; + } + + private void buildPartial0(com.google.storage.v2.ObjectContexts result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.custom_ = internalGetCustom().build(CustomDefaultEntryHolder.defaultEntry); + } + } + + @java.lang.Override + public Builder clone() { + return super.clone(); + } + + @java.lang.Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) { + return super.setField(field, value); + } + + @java.lang.Override + public Builder clearField(com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + + @java.lang.Override + public Builder clearOneof(com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + + @java.lang.Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); + } + + @java.lang.Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) { + return super.addRepeatedField(field, value); + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof com.google.storage.v2.ObjectContexts) { + return mergeFrom((com.google.storage.v2.ObjectContexts) other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(com.google.storage.v2.ObjectContexts other) { + if (other == com.google.storage.v2.ObjectContexts.getDefaultInstance()) return this; + internalGetMutableCustom().mergeFrom(other.internalGetCustom()); + bitField0_ |= 0x00000001; + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: + { + com.google.protobuf.MapEntry< + java.lang.String, com.google.storage.v2.ObjectCustomContextPayload> + custom__ = + input.readMessage( + CustomDefaultEntryHolder.defaultEntry.getParserForType(), + extensionRegistry); + internalGetMutableCustom() + .ensureBuilderMap() + .put(custom__.getKey(), custom__.getValue()); + bitField0_ |= 0x00000001; + break; + } // case 10 + default: + { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + + private int bitField0_; + + private static final class CustomConverter + implements com.google.protobuf.MapFieldBuilder.Converter< + java.lang.String, + com.google.storage.v2.ObjectCustomContextPayloadOrBuilder, + com.google.storage.v2.ObjectCustomContextPayload> { + @java.lang.Override + public com.google.storage.v2.ObjectCustomContextPayload build( + com.google.storage.v2.ObjectCustomContextPayloadOrBuilder val) { + if (val instanceof com.google.storage.v2.ObjectCustomContextPayload) { + return (com.google.storage.v2.ObjectCustomContextPayload) val; + } + return ((com.google.storage.v2.ObjectCustomContextPayload.Builder) val).build(); + } + + @java.lang.Override + public com.google.protobuf.MapEntry< + java.lang.String, com.google.storage.v2.ObjectCustomContextPayload> + defaultEntry() { + return CustomDefaultEntryHolder.defaultEntry; + } + } + ; + + private static final CustomConverter customConverter = new CustomConverter(); + + private com.google.protobuf.MapFieldBuilder< + java.lang.String, + com.google.storage.v2.ObjectCustomContextPayloadOrBuilder, + com.google.storage.v2.ObjectCustomContextPayload, + com.google.storage.v2.ObjectCustomContextPayload.Builder> + custom_; + + private com.google.protobuf.MapFieldBuilder< + java.lang.String, + com.google.storage.v2.ObjectCustomContextPayloadOrBuilder, + com.google.storage.v2.ObjectCustomContextPayload, + com.google.storage.v2.ObjectCustomContextPayload.Builder> + internalGetCustom() { + if (custom_ == null) { + return new com.google.protobuf.MapFieldBuilder<>(customConverter); + } + return custom_; + } + + private com.google.protobuf.MapFieldBuilder< + java.lang.String, + com.google.storage.v2.ObjectCustomContextPayloadOrBuilder, + com.google.storage.v2.ObjectCustomContextPayload, + com.google.storage.v2.ObjectCustomContextPayload.Builder> + internalGetMutableCustom() { + if (custom_ == null) { + custom_ = new com.google.protobuf.MapFieldBuilder<>(customConverter); + } + bitField0_ |= 0x00000001; + onChanged(); + return custom_; + } + + public int getCustomCount() { + return internalGetCustom().ensureBuilderMap().size(); + } + + /** + * + * + *
+     * Optional. User-defined object contexts.
+     * 
+ * + * + * map<string, .google.storage.v2.ObjectCustomContextPayload> custom = 1 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + @java.lang.Override + public boolean containsCustom(java.lang.String key) { + if (key == null) { + throw new NullPointerException("map key"); + } + return internalGetCustom().ensureBuilderMap().containsKey(key); + } + + /** Use {@link #getCustomMap()} instead. */ + @java.lang.Override + @java.lang.Deprecated + public java.util.Map + getCustom() { + return getCustomMap(); + } + + /** + * + * + *
+     * Optional. User-defined object contexts.
+     * 
+ * + * + * map<string, .google.storage.v2.ObjectCustomContextPayload> custom = 1 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + @java.lang.Override + public java.util.Map + getCustomMap() { + return internalGetCustom().getImmutableMap(); + } + + /** + * + * + *
+     * Optional. User-defined object contexts.
+     * 
+ * + * + * map<string, .google.storage.v2.ObjectCustomContextPayload> custom = 1 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + @java.lang.Override + public /* nullable */ com.google.storage.v2.ObjectCustomContextPayload getCustomOrDefault( + java.lang.String key, + /* nullable */ + com.google.storage.v2.ObjectCustomContextPayload defaultValue) { + if (key == null) { + throw new NullPointerException("map key"); + } + java.util.Map + map = internalGetMutableCustom().ensureBuilderMap(); + return map.containsKey(key) ? customConverter.build(map.get(key)) : defaultValue; + } + + /** + * + * + *
+     * Optional. User-defined object contexts.
+     * 
+ * + * + * map<string, .google.storage.v2.ObjectCustomContextPayload> custom = 1 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + @java.lang.Override + public com.google.storage.v2.ObjectCustomContextPayload getCustomOrThrow(java.lang.String key) { + if (key == null) { + throw new NullPointerException("map key"); + } + java.util.Map + map = internalGetMutableCustom().ensureBuilderMap(); + if (!map.containsKey(key)) { + throw new java.lang.IllegalArgumentException(); + } + return customConverter.build(map.get(key)); + } + + public Builder clearCustom() { + bitField0_ = (bitField0_ & ~0x00000001); + internalGetMutableCustom().clear(); + return this; + } + + /** + * + * + *
+     * Optional. User-defined object contexts.
+     * 
+ * + * + * map<string, .google.storage.v2.ObjectCustomContextPayload> custom = 1 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + public Builder removeCustom(java.lang.String key) { + if (key == null) { + throw new NullPointerException("map key"); + } + internalGetMutableCustom().ensureBuilderMap().remove(key); + return this; + } + + /** Use alternate mutation accessors instead. */ + @java.lang.Deprecated + public java.util.Map + getMutableCustom() { + bitField0_ |= 0x00000001; + return internalGetMutableCustom().ensureMessageMap(); + } + + /** + * + * + *
+     * Optional. User-defined object contexts.
+     * 
+ * + * + * map<string, .google.storage.v2.ObjectCustomContextPayload> custom = 1 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + public Builder putCustom( + java.lang.String key, com.google.storage.v2.ObjectCustomContextPayload value) { + if (key == null) { + throw new NullPointerException("map key"); + } + if (value == null) { + throw new NullPointerException("map value"); + } + internalGetMutableCustom().ensureBuilderMap().put(key, value); + bitField0_ |= 0x00000001; + return this; + } + + /** + * + * + *
+     * Optional. User-defined object contexts.
+     * 
+ * + * + * map<string, .google.storage.v2.ObjectCustomContextPayload> custom = 1 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + public Builder putAllCustom( + java.util.Map values) { + for (java.util.Map.Entry + e : values.entrySet()) { + if (e.getKey() == null || e.getValue() == null) { + throw new NullPointerException(); + } + } + internalGetMutableCustom().ensureBuilderMap().putAll(values); + bitField0_ |= 0x00000001; + return this; + } + + /** + * + * + *
+     * Optional. User-defined object contexts.
+     * 
+ * + * + * map<string, .google.storage.v2.ObjectCustomContextPayload> custom = 1 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + public com.google.storage.v2.ObjectCustomContextPayload.Builder putCustomBuilderIfAbsent( + java.lang.String key) { + java.util.Map + builderMap = internalGetMutableCustom().ensureBuilderMap(); + com.google.storage.v2.ObjectCustomContextPayloadOrBuilder entry = builderMap.get(key); + if (entry == null) { + entry = com.google.storage.v2.ObjectCustomContextPayload.newBuilder(); + builderMap.put(key, entry); + } + if (entry instanceof com.google.storage.v2.ObjectCustomContextPayload) { + entry = ((com.google.storage.v2.ObjectCustomContextPayload) entry).toBuilder(); + builderMap.put(key, entry); + } + return (com.google.storage.v2.ObjectCustomContextPayload.Builder) entry; + } + + @java.lang.Override + public final Builder setUnknownFields(final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @java.lang.Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + // @@protoc_insertion_point(builder_scope:google.storage.v2.ObjectContexts) + } + + // @@protoc_insertion_point(class_scope:google.storage.v2.ObjectContexts) + private static final com.google.storage.v2.ObjectContexts DEFAULT_INSTANCE; + + static { + DEFAULT_INSTANCE = new com.google.storage.v2.ObjectContexts(); + } + + public static com.google.storage.v2.ObjectContexts getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser PARSER = + new com.google.protobuf.AbstractParser() { + @java.lang.Override + public ObjectContexts parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public com.google.storage.v2.ObjectContexts getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } +} diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectContextsOrBuilder.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectContextsOrBuilder.java new file mode 100644 index 000000000..db6a67b6a --- /dev/null +++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectContextsOrBuilder.java @@ -0,0 +1,99 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/storage/v2/storage.proto + +// Protobuf Java Version: 3.25.8 +package com.google.storage.v2; + +public interface ObjectContextsOrBuilder + extends + // @@protoc_insertion_point(interface_extends:google.storage.v2.ObjectContexts) + com.google.protobuf.MessageOrBuilder { + + /** + * + * + *
+   * Optional. User-defined object contexts.
+   * 
+ * + * + * map<string, .google.storage.v2.ObjectCustomContextPayload> custom = 1 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + int getCustomCount(); + + /** + * + * + *
+   * Optional. User-defined object contexts.
+   * 
+ * + * + * map<string, .google.storage.v2.ObjectCustomContextPayload> custom = 1 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + boolean containsCustom(java.lang.String key); + + /** Use {@link #getCustomMap()} instead. */ + @java.lang.Deprecated + java.util.Map getCustom(); + + /** + * + * + *
+   * Optional. User-defined object contexts.
+   * 
+ * + * + * map<string, .google.storage.v2.ObjectCustomContextPayload> custom = 1 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + java.util.Map getCustomMap(); + + /** + * + * + *
+   * Optional. User-defined object contexts.
+   * 
+ * + * + * map<string, .google.storage.v2.ObjectCustomContextPayload> custom = 1 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + /* nullable */ + com.google.storage.v2.ObjectCustomContextPayload getCustomOrDefault( + java.lang.String key, + /* nullable */ + com.google.storage.v2.ObjectCustomContextPayload defaultValue); + + /** + * + * + *
+   * Optional. User-defined object contexts.
+   * 
+ * + * + * map<string, .google.storage.v2.ObjectCustomContextPayload> custom = 1 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + com.google.storage.v2.ObjectCustomContextPayload getCustomOrThrow(java.lang.String key); +} diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectCustomContextPayload.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectCustomContextPayload.java new file mode 100644 index 000000000..a76cea296 --- /dev/null +++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectCustomContextPayload.java @@ -0,0 +1,1239 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/storage/v2/storage.proto + +// Protobuf Java Version: 3.25.8 +package com.google.storage.v2; + +/** + * + * + *
+ * The payload of a single user-defined object context.
+ * 
+ * + * Protobuf type {@code google.storage.v2.ObjectCustomContextPayload} + */ +public final class ObjectCustomContextPayload extends com.google.protobuf.GeneratedMessageV3 + implements + // @@protoc_insertion_point(message_implements:google.storage.v2.ObjectCustomContextPayload) + ObjectCustomContextPayloadOrBuilder { + private static final long serialVersionUID = 0L; + + // Use ObjectCustomContextPayload.newBuilder() to construct. + private ObjectCustomContextPayload(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + + private ObjectCustomContextPayload() { + value_ = ""; + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance(UnusedPrivateParameter unused) { + return new ObjectCustomContextPayload(); + } + + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { + return com.google.storage.v2.StorageProto + .internal_static_google_storage_v2_ObjectCustomContextPayload_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.google.storage.v2.StorageProto + .internal_static_google_storage_v2_ObjectCustomContextPayload_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.google.storage.v2.ObjectCustomContextPayload.class, + com.google.storage.v2.ObjectCustomContextPayload.Builder.class); + } + + private int bitField0_; + public static final int VALUE_FIELD_NUMBER = 1; + + @SuppressWarnings("serial") + private volatile java.lang.Object value_ = ""; + + /** + * + * + *
+   * Required. The value of the object context.
+   * 
+ * + * string value = 1 [(.google.api.field_behavior) = REQUIRED]; + * + * @return The value. + */ + @java.lang.Override + public java.lang.String getValue() { + java.lang.Object ref = value_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + value_ = s; + return s; + } + } + + /** + * + * + *
+   * Required. The value of the object context.
+   * 
+ * + * string value = 1 [(.google.api.field_behavior) = REQUIRED]; + * + * @return The bytes for value. + */ + @java.lang.Override + public com.google.protobuf.ByteString getValueBytes() { + java.lang.Object ref = value_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); + value_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int CREATE_TIME_FIELD_NUMBER = 2; + private com.google.protobuf.Timestamp createTime_; + + /** + * + * + *
+   * Output only. The time at which the object context was created.
+   * 
+ * + * .google.protobuf.Timestamp create_time = 2 [(.google.api.field_behavior) = OUTPUT_ONLY]; + * + * + * @return Whether the createTime field is set. + */ + @java.lang.Override + public boolean hasCreateTime() { + return ((bitField0_ & 0x00000001) != 0); + } + + /** + * + * + *
+   * Output only. The time at which the object context was created.
+   * 
+ * + * .google.protobuf.Timestamp create_time = 2 [(.google.api.field_behavior) = OUTPUT_ONLY]; + * + * + * @return The createTime. + */ + @java.lang.Override + public com.google.protobuf.Timestamp getCreateTime() { + return createTime_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : createTime_; + } + + /** + * + * + *
+   * Output only. The time at which the object context was created.
+   * 
+ * + * .google.protobuf.Timestamp create_time = 2 [(.google.api.field_behavior) = OUTPUT_ONLY]; + * + */ + @java.lang.Override + public com.google.protobuf.TimestampOrBuilder getCreateTimeOrBuilder() { + return createTime_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : createTime_; + } + + public static final int UPDATE_TIME_FIELD_NUMBER = 3; + private com.google.protobuf.Timestamp updateTime_; + + /** + * + * + *
+   * Output only. The time at which the object context was last updated.
+   * 
+ * + * .google.protobuf.Timestamp update_time = 3 [(.google.api.field_behavior) = OUTPUT_ONLY]; + * + * + * @return Whether the updateTime field is set. + */ + @java.lang.Override + public boolean hasUpdateTime() { + return ((bitField0_ & 0x00000002) != 0); + } + + /** + * + * + *
+   * Output only. The time at which the object context was last updated.
+   * 
+ * + * .google.protobuf.Timestamp update_time = 3 [(.google.api.field_behavior) = OUTPUT_ONLY]; + * + * + * @return The updateTime. + */ + @java.lang.Override + public com.google.protobuf.Timestamp getUpdateTime() { + return updateTime_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : updateTime_; + } + + /** + * + * + *
+   * Output only. The time at which the object context was last updated.
+   * 
+ * + * .google.protobuf.Timestamp update_time = 3 [(.google.api.field_behavior) = OUTPUT_ONLY]; + * + */ + @java.lang.Override + public com.google.protobuf.TimestampOrBuilder getUpdateTimeOrBuilder() { + return updateTime_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : updateTime_; + } + + private byte memoizedIsInitialized = -1; + + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(value_)) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 1, value_); + } + if (((bitField0_ & 0x00000001) != 0)) { + output.writeMessage(2, getCreateTime()); + } + if (((bitField0_ & 0x00000002) != 0)) { + output.writeMessage(3, getUpdateTime()); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(value_)) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, value_); + } + if (((bitField0_ & 0x00000001) != 0)) { + size += com.google.protobuf.CodedOutputStream.computeMessageSize(2, getCreateTime()); + } + if (((bitField0_ & 0x00000002) != 0)) { + size += com.google.protobuf.CodedOutputStream.computeMessageSize(3, getUpdateTime()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof com.google.storage.v2.ObjectCustomContextPayload)) { + return super.equals(obj); + } + com.google.storage.v2.ObjectCustomContextPayload other = + (com.google.storage.v2.ObjectCustomContextPayload) obj; + + if (!getValue().equals(other.getValue())) return false; + if (hasCreateTime() != other.hasCreateTime()) return false; + if (hasCreateTime()) { + if (!getCreateTime().equals(other.getCreateTime())) return false; + } + if (hasUpdateTime() != other.hasUpdateTime()) return false; + if (hasUpdateTime()) { + if (!getUpdateTime().equals(other.getUpdateTime())) return false; + } + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + VALUE_FIELD_NUMBER; + hash = (53 * hash) + getValue().hashCode(); + if (hasCreateTime()) { + hash = (37 * hash) + CREATE_TIME_FIELD_NUMBER; + hash = (53 * hash) + getCreateTime().hashCode(); + } + if (hasUpdateTime()) { + hash = (37 * hash) + UPDATE_TIME_FIELD_NUMBER; + hash = (53 * hash) + getUpdateTime().hashCode(); + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static com.google.storage.v2.ObjectCustomContextPayload parseFrom(java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static com.google.storage.v2.ObjectCustomContextPayload parseFrom( + java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static com.google.storage.v2.ObjectCustomContextPayload parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static com.google.storage.v2.ObjectCustomContextPayload parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static com.google.storage.v2.ObjectCustomContextPayload parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static com.google.storage.v2.ObjectCustomContextPayload parseFrom( + byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static com.google.storage.v2.ObjectCustomContextPayload parseFrom( + java.io.InputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input); + } + + public static com.google.storage.v2.ObjectCustomContextPayload parseFrom( + java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseWithIOException( + PARSER, input, extensionRegistry); + } + + public static com.google.storage.v2.ObjectCustomContextPayload parseDelimitedFrom( + java.io.InputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException(PARSER, input); + } + + public static com.google.storage.v2.ObjectCustomContextPayload parseDelimitedFrom( + java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException( + PARSER, input, extensionRegistry); + } + + public static com.google.storage.v2.ObjectCustomContextPayload parseFrom( + com.google.protobuf.CodedInputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input); + } + + public static com.google.storage.v2.ObjectCustomContextPayload parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseWithIOException( + PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { + return newBuilder(); + } + + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + + public static Builder newBuilder(com.google.storage.v2.ObjectCustomContextPayload prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType(com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + + /** + * + * + *
+   * The payload of a single user-defined object context.
+   * 
+ * + * Protobuf type {@code google.storage.v2.ObjectCustomContextPayload} + */ + public static final class Builder extends com.google.protobuf.GeneratedMessageV3.Builder + implements + // @@protoc_insertion_point(builder_implements:google.storage.v2.ObjectCustomContextPayload) + com.google.storage.v2.ObjectCustomContextPayloadOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { + return com.google.storage.v2.StorageProto + .internal_static_google_storage_v2_ObjectCustomContextPayload_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.google.storage.v2.StorageProto + .internal_static_google_storage_v2_ObjectCustomContextPayload_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.google.storage.v2.ObjectCustomContextPayload.class, + com.google.storage.v2.ObjectCustomContextPayload.Builder.class); + } + + // Construct using com.google.storage.v2.ObjectCustomContextPayload.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder(com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders) { + getCreateTimeFieldBuilder(); + getUpdateTimeFieldBuilder(); + } + } + + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + value_ = ""; + createTime_ = null; + if (createTimeBuilder_ != null) { + createTimeBuilder_.dispose(); + createTimeBuilder_ = null; + } + updateTime_ = null; + if (updateTimeBuilder_ != null) { + updateTimeBuilder_.dispose(); + updateTimeBuilder_ = null; + } + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { + return com.google.storage.v2.StorageProto + .internal_static_google_storage_v2_ObjectCustomContextPayload_descriptor; + } + + @java.lang.Override + public com.google.storage.v2.ObjectCustomContextPayload getDefaultInstanceForType() { + return com.google.storage.v2.ObjectCustomContextPayload.getDefaultInstance(); + } + + @java.lang.Override + public com.google.storage.v2.ObjectCustomContextPayload build() { + com.google.storage.v2.ObjectCustomContextPayload result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public com.google.storage.v2.ObjectCustomContextPayload buildPartial() { + com.google.storage.v2.ObjectCustomContextPayload result = + new com.google.storage.v2.ObjectCustomContextPayload(this); + if (bitField0_ != 0) { + buildPartial0(result); + } + onBuilt(); + return result; + } + + private void buildPartial0(com.google.storage.v2.ObjectCustomContextPayload result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.value_ = value_; + } + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000002) != 0)) { + result.createTime_ = createTimeBuilder_ == null ? createTime_ : createTimeBuilder_.build(); + to_bitField0_ |= 0x00000001; + } + if (((from_bitField0_ & 0x00000004) != 0)) { + result.updateTime_ = updateTimeBuilder_ == null ? updateTime_ : updateTimeBuilder_.build(); + to_bitField0_ |= 0x00000002; + } + result.bitField0_ |= to_bitField0_; + } + + @java.lang.Override + public Builder clone() { + return super.clone(); + } + + @java.lang.Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) { + return super.setField(field, value); + } + + @java.lang.Override + public Builder clearField(com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + + @java.lang.Override + public Builder clearOneof(com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + + @java.lang.Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); + } + + @java.lang.Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) { + return super.addRepeatedField(field, value); + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof com.google.storage.v2.ObjectCustomContextPayload) { + return mergeFrom((com.google.storage.v2.ObjectCustomContextPayload) other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(com.google.storage.v2.ObjectCustomContextPayload other) { + if (other == com.google.storage.v2.ObjectCustomContextPayload.getDefaultInstance()) + return this; + if (!other.getValue().isEmpty()) { + value_ = other.value_; + bitField0_ |= 0x00000001; + onChanged(); + } + if (other.hasCreateTime()) { + mergeCreateTime(other.getCreateTime()); + } + if (other.hasUpdateTime()) { + mergeUpdateTime(other.getUpdateTime()); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: + { + value_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + case 18: + { + input.readMessage(getCreateTimeFieldBuilder().getBuilder(), extensionRegistry); + bitField0_ |= 0x00000002; + break; + } // case 18 + case 26: + { + input.readMessage(getUpdateTimeFieldBuilder().getBuilder(), extensionRegistry); + bitField0_ |= 0x00000004; + break; + } // case 26 + default: + { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + + private int bitField0_; + + private java.lang.Object value_ = ""; + + /** + * + * + *
+     * Required. The value of the object context.
+     * 
+ * + * string value = 1 [(.google.api.field_behavior) = REQUIRED]; + * + * @return The value. + */ + public java.lang.String getValue() { + java.lang.Object ref = value_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + value_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + + /** + * + * + *
+     * Required. The value of the object context.
+     * 
+ * + * string value = 1 [(.google.api.field_behavior) = REQUIRED]; + * + * @return The bytes for value. + */ + public com.google.protobuf.ByteString getValueBytes() { + java.lang.Object ref = value_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); + value_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + /** + * + * + *
+     * Required. The value of the object context.
+     * 
+ * + * string value = 1 [(.google.api.field_behavior) = REQUIRED]; + * + * @param value The value to set. + * @return This builder for chaining. + */ + public Builder setValue(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + value_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + /** + * + * + *
+     * Required. The value of the object context.
+     * 
+ * + * string value = 1 [(.google.api.field_behavior) = REQUIRED]; + * + * @return This builder for chaining. + */ + public Builder clearValue() { + value_ = getDefaultInstance().getValue(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + + /** + * + * + *
+     * Required. The value of the object context.
+     * 
+ * + * string value = 1 [(.google.api.field_behavior) = REQUIRED]; + * + * @param value The bytes for value to set. + * @return This builder for chaining. + */ + public Builder setValueBytes(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + value_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + private com.google.protobuf.Timestamp createTime_; + private com.google.protobuf.SingleFieldBuilderV3< + com.google.protobuf.Timestamp, + com.google.protobuf.Timestamp.Builder, + com.google.protobuf.TimestampOrBuilder> + createTimeBuilder_; + + /** + * + * + *
+     * Output only. The time at which the object context was created.
+     * 
+ * + * + * .google.protobuf.Timestamp create_time = 2 [(.google.api.field_behavior) = OUTPUT_ONLY]; + * + * + * @return Whether the createTime field is set. + */ + public boolean hasCreateTime() { + return ((bitField0_ & 0x00000002) != 0); + } + + /** + * + * + *
+     * Output only. The time at which the object context was created.
+     * 
+ * + * + * .google.protobuf.Timestamp create_time = 2 [(.google.api.field_behavior) = OUTPUT_ONLY]; + * + * + * @return The createTime. + */ + public com.google.protobuf.Timestamp getCreateTime() { + if (createTimeBuilder_ == null) { + return createTime_ == null + ? com.google.protobuf.Timestamp.getDefaultInstance() + : createTime_; + } else { + return createTimeBuilder_.getMessage(); + } + } + + /** + * + * + *
+     * Output only. The time at which the object context was created.
+     * 
+ * + * + * .google.protobuf.Timestamp create_time = 2 [(.google.api.field_behavior) = OUTPUT_ONLY]; + * + */ + public Builder setCreateTime(com.google.protobuf.Timestamp value) { + if (createTimeBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + createTime_ = value; + } else { + createTimeBuilder_.setMessage(value); + } + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + + /** + * + * + *
+     * Output only. The time at which the object context was created.
+     * 
+ * + * + * .google.protobuf.Timestamp create_time = 2 [(.google.api.field_behavior) = OUTPUT_ONLY]; + * + */ + public Builder setCreateTime(com.google.protobuf.Timestamp.Builder builderForValue) { + if (createTimeBuilder_ == null) { + createTime_ = builderForValue.build(); + } else { + createTimeBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + + /** + * + * + *
+     * Output only. The time at which the object context was created.
+     * 
+ * + * + * .google.protobuf.Timestamp create_time = 2 [(.google.api.field_behavior) = OUTPUT_ONLY]; + * + */ + public Builder mergeCreateTime(com.google.protobuf.Timestamp value) { + if (createTimeBuilder_ == null) { + if (((bitField0_ & 0x00000002) != 0) + && createTime_ != null + && createTime_ != com.google.protobuf.Timestamp.getDefaultInstance()) { + getCreateTimeBuilder().mergeFrom(value); + } else { + createTime_ = value; + } + } else { + createTimeBuilder_.mergeFrom(value); + } + if (createTime_ != null) { + bitField0_ |= 0x00000002; + onChanged(); + } + return this; + } + + /** + * + * + *
+     * Output only. The time at which the object context was created.
+     * 
+ * + * + * .google.protobuf.Timestamp create_time = 2 [(.google.api.field_behavior) = OUTPUT_ONLY]; + * + */ + public Builder clearCreateTime() { + bitField0_ = (bitField0_ & ~0x00000002); + createTime_ = null; + if (createTimeBuilder_ != null) { + createTimeBuilder_.dispose(); + createTimeBuilder_ = null; + } + onChanged(); + return this; + } + + /** + * + * + *
+     * Output only. The time at which the object context was created.
+     * 
+ * + * + * .google.protobuf.Timestamp create_time = 2 [(.google.api.field_behavior) = OUTPUT_ONLY]; + * + */ + public com.google.protobuf.Timestamp.Builder getCreateTimeBuilder() { + bitField0_ |= 0x00000002; + onChanged(); + return getCreateTimeFieldBuilder().getBuilder(); + } + + /** + * + * + *
+     * Output only. The time at which the object context was created.
+     * 
+ * + * + * .google.protobuf.Timestamp create_time = 2 [(.google.api.field_behavior) = OUTPUT_ONLY]; + * + */ + public com.google.protobuf.TimestampOrBuilder getCreateTimeOrBuilder() { + if (createTimeBuilder_ != null) { + return createTimeBuilder_.getMessageOrBuilder(); + } else { + return createTime_ == null + ? com.google.protobuf.Timestamp.getDefaultInstance() + : createTime_; + } + } + + /** + * + * + *
+     * Output only. The time at which the object context was created.
+     * 
+ * + * + * .google.protobuf.Timestamp create_time = 2 [(.google.api.field_behavior) = OUTPUT_ONLY]; + * + */ + private com.google.protobuf.SingleFieldBuilderV3< + com.google.protobuf.Timestamp, + com.google.protobuf.Timestamp.Builder, + com.google.protobuf.TimestampOrBuilder> + getCreateTimeFieldBuilder() { + if (createTimeBuilder_ == null) { + createTimeBuilder_ = + new com.google.protobuf.SingleFieldBuilderV3< + com.google.protobuf.Timestamp, + com.google.protobuf.Timestamp.Builder, + com.google.protobuf.TimestampOrBuilder>( + getCreateTime(), getParentForChildren(), isClean()); + createTime_ = null; + } + return createTimeBuilder_; + } + + private com.google.protobuf.Timestamp updateTime_; + private com.google.protobuf.SingleFieldBuilderV3< + com.google.protobuf.Timestamp, + com.google.protobuf.Timestamp.Builder, + com.google.protobuf.TimestampOrBuilder> + updateTimeBuilder_; + + /** + * + * + *
+     * Output only. The time at which the object context was last updated.
+     * 
+ * + * + * .google.protobuf.Timestamp update_time = 3 [(.google.api.field_behavior) = OUTPUT_ONLY]; + * + * + * @return Whether the updateTime field is set. + */ + public boolean hasUpdateTime() { + return ((bitField0_ & 0x00000004) != 0); + } + + /** + * + * + *
+     * Output only. The time at which the object context was last updated.
+     * 
+ * + * + * .google.protobuf.Timestamp update_time = 3 [(.google.api.field_behavior) = OUTPUT_ONLY]; + * + * + * @return The updateTime. + */ + public com.google.protobuf.Timestamp getUpdateTime() { + if (updateTimeBuilder_ == null) { + return updateTime_ == null + ? com.google.protobuf.Timestamp.getDefaultInstance() + : updateTime_; + } else { + return updateTimeBuilder_.getMessage(); + } + } + + /** + * + * + *
+     * Output only. The time at which the object context was last updated.
+     * 
+ * + * + * .google.protobuf.Timestamp update_time = 3 [(.google.api.field_behavior) = OUTPUT_ONLY]; + * + */ + public Builder setUpdateTime(com.google.protobuf.Timestamp value) { + if (updateTimeBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + updateTime_ = value; + } else { + updateTimeBuilder_.setMessage(value); + } + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + + /** + * + * + *
+     * Output only. The time at which the object context was last updated.
+     * 
+ * + * + * .google.protobuf.Timestamp update_time = 3 [(.google.api.field_behavior) = OUTPUT_ONLY]; + * + */ + public Builder setUpdateTime(com.google.protobuf.Timestamp.Builder builderForValue) { + if (updateTimeBuilder_ == null) { + updateTime_ = builderForValue.build(); + } else { + updateTimeBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + + /** + * + * + *
+     * Output only. The time at which the object context was last updated.
+     * 
+ * + * + * .google.protobuf.Timestamp update_time = 3 [(.google.api.field_behavior) = OUTPUT_ONLY]; + * + */ + public Builder mergeUpdateTime(com.google.protobuf.Timestamp value) { + if (updateTimeBuilder_ == null) { + if (((bitField0_ & 0x00000004) != 0) + && updateTime_ != null + && updateTime_ != com.google.protobuf.Timestamp.getDefaultInstance()) { + getUpdateTimeBuilder().mergeFrom(value); + } else { + updateTime_ = value; + } + } else { + updateTimeBuilder_.mergeFrom(value); + } + if (updateTime_ != null) { + bitField0_ |= 0x00000004; + onChanged(); + } + return this; + } + + /** + * + * + *
+     * Output only. The time at which the object context was last updated.
+     * 
+ * + * + * .google.protobuf.Timestamp update_time = 3 [(.google.api.field_behavior) = OUTPUT_ONLY]; + * + */ + public Builder clearUpdateTime() { + bitField0_ = (bitField0_ & ~0x00000004); + updateTime_ = null; + if (updateTimeBuilder_ != null) { + updateTimeBuilder_.dispose(); + updateTimeBuilder_ = null; + } + onChanged(); + return this; + } + + /** + * + * + *
+     * Output only. The time at which the object context was last updated.
+     * 
+ * + * + * .google.protobuf.Timestamp update_time = 3 [(.google.api.field_behavior) = OUTPUT_ONLY]; + * + */ + public com.google.protobuf.Timestamp.Builder getUpdateTimeBuilder() { + bitField0_ |= 0x00000004; + onChanged(); + return getUpdateTimeFieldBuilder().getBuilder(); + } + + /** + * + * + *
+     * Output only. The time at which the object context was last updated.
+     * 
+ * + * + * .google.protobuf.Timestamp update_time = 3 [(.google.api.field_behavior) = OUTPUT_ONLY]; + * + */ + public com.google.protobuf.TimestampOrBuilder getUpdateTimeOrBuilder() { + if (updateTimeBuilder_ != null) { + return updateTimeBuilder_.getMessageOrBuilder(); + } else { + return updateTime_ == null + ? com.google.protobuf.Timestamp.getDefaultInstance() + : updateTime_; + } + } + + /** + * + * + *
+     * Output only. The time at which the object context was last updated.
+     * 
+ * + * + * .google.protobuf.Timestamp update_time = 3 [(.google.api.field_behavior) = OUTPUT_ONLY]; + * + */ + private com.google.protobuf.SingleFieldBuilderV3< + com.google.protobuf.Timestamp, + com.google.protobuf.Timestamp.Builder, + com.google.protobuf.TimestampOrBuilder> + getUpdateTimeFieldBuilder() { + if (updateTimeBuilder_ == null) { + updateTimeBuilder_ = + new com.google.protobuf.SingleFieldBuilderV3< + com.google.protobuf.Timestamp, + com.google.protobuf.Timestamp.Builder, + com.google.protobuf.TimestampOrBuilder>( + getUpdateTime(), getParentForChildren(), isClean()); + updateTime_ = null; + } + return updateTimeBuilder_; + } + + @java.lang.Override + public final Builder setUnknownFields(final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @java.lang.Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + // @@protoc_insertion_point(builder_scope:google.storage.v2.ObjectCustomContextPayload) + } + + // @@protoc_insertion_point(class_scope:google.storage.v2.ObjectCustomContextPayload) + private static final com.google.storage.v2.ObjectCustomContextPayload DEFAULT_INSTANCE; + + static { + DEFAULT_INSTANCE = new com.google.storage.v2.ObjectCustomContextPayload(); + } + + public static com.google.storage.v2.ObjectCustomContextPayload getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser PARSER = + new com.google.protobuf.AbstractParser() { + @java.lang.Override + public ObjectCustomContextPayload parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public com.google.storage.v2.ObjectCustomContextPayload getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } +} diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectCustomContextPayloadOrBuilder.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectCustomContextPayloadOrBuilder.java new file mode 100644 index 000000000..e973d9a0b --- /dev/null +++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectCustomContextPayloadOrBuilder.java @@ -0,0 +1,132 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/storage/v2/storage.proto + +// Protobuf Java Version: 3.25.8 +package com.google.storage.v2; + +public interface ObjectCustomContextPayloadOrBuilder + extends + // @@protoc_insertion_point(interface_extends:google.storage.v2.ObjectCustomContextPayload) + com.google.protobuf.MessageOrBuilder { + + /** + * + * + *
+   * Required. The value of the object context.
+   * 
+ * + * string value = 1 [(.google.api.field_behavior) = REQUIRED]; + * + * @return The value. + */ + java.lang.String getValue(); + + /** + * + * + *
+   * Required. The value of the object context.
+   * 
+ * + * string value = 1 [(.google.api.field_behavior) = REQUIRED]; + * + * @return The bytes for value. + */ + com.google.protobuf.ByteString getValueBytes(); + + /** + * + * + *
+   * Output only. The time at which the object context was created.
+   * 
+ * + * .google.protobuf.Timestamp create_time = 2 [(.google.api.field_behavior) = OUTPUT_ONLY]; + * + * + * @return Whether the createTime field is set. + */ + boolean hasCreateTime(); + + /** + * + * + *
+   * Output only. The time at which the object context was created.
+   * 
+ * + * .google.protobuf.Timestamp create_time = 2 [(.google.api.field_behavior) = OUTPUT_ONLY]; + * + * + * @return The createTime. + */ + com.google.protobuf.Timestamp getCreateTime(); + + /** + * + * + *
+   * Output only. The time at which the object context was created.
+   * 
+ * + * .google.protobuf.Timestamp create_time = 2 [(.google.api.field_behavior) = OUTPUT_ONLY]; + * + */ + com.google.protobuf.TimestampOrBuilder getCreateTimeOrBuilder(); + + /** + * + * + *
+   * Output only. The time at which the object context was last updated.
+   * 
+ * + * .google.protobuf.Timestamp update_time = 3 [(.google.api.field_behavior) = OUTPUT_ONLY]; + * + * + * @return Whether the updateTime field is set. + */ + boolean hasUpdateTime(); + + /** + * + * + *
+   * Output only. The time at which the object context was last updated.
+   * 
+ * + * .google.protobuf.Timestamp update_time = 3 [(.google.api.field_behavior) = OUTPUT_ONLY]; + * + * + * @return The updateTime. + */ + com.google.protobuf.Timestamp getUpdateTime(); + + /** + * + * + *
+   * Output only. The time at which the object context was last updated.
+   * 
+ * + * .google.protobuf.Timestamp update_time = 3 [(.google.api.field_behavior) = OUTPUT_ONLY]; + * + */ + com.google.protobuf.TimestampOrBuilder getUpdateTimeOrBuilder(); +} diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectOrBuilder.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectOrBuilder.java index e9a35b73c..9c0b359da 100644 --- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectOrBuilder.java +++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/ObjectOrBuilder.java @@ -930,6 +930,55 @@ java.lang.String getMetadataOrDefault( */ java.lang.String getMetadataOrThrow(java.lang.String key); + /** + * + * + *
+   * Optional. User-defined or system-defined object contexts. Each object
+   * context is a key-payload pair, where the key provides the identification
+   * and the payload holds the associated value and additional metadata.
+   * 
+ * + * + * .google.storage.v2.ObjectContexts contexts = 38 [(.google.api.field_behavior) = OPTIONAL]; + * + * + * @return Whether the contexts field is set. + */ + boolean hasContexts(); + + /** + * + * + *
+   * Optional. User-defined or system-defined object contexts. Each object
+   * context is a key-payload pair, where the key provides the identification
+   * and the payload holds the associated value and additional metadata.
+   * 
+ * + * + * .google.storage.v2.ObjectContexts contexts = 38 [(.google.api.field_behavior) = OPTIONAL]; + * + * + * @return The contexts. + */ + com.google.storage.v2.ObjectContexts getContexts(); + + /** + * + * + *
+   * Optional. User-defined or system-defined object contexts. Each object
+   * context is a key-payload pair, where the key provides the identification
+   * and the payload holds the associated value and additional metadata.
+   * 
+ * + * + * .google.storage.v2.ObjectContexts contexts = 38 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + com.google.storage.v2.ObjectContextsOrBuilder getContextsOrBuilder(); + /** * * diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageProto.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageProto.java index b92ae234f..36d6c8d9e 100644 --- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageProto.java +++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/StorageProto.java @@ -324,6 +324,18 @@ public static void registerAllExtensions(com.google.protobuf.ExtensionRegistry r internal_static_google_storage_v2_ObjectChecksums_descriptor; static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internal_static_google_storage_v2_ObjectChecksums_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_google_storage_v2_ObjectCustomContextPayload_descriptor; + static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_google_storage_v2_ObjectCustomContextPayload_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_google_storage_v2_ObjectContexts_descriptor; + static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_google_storage_v2_ObjectContexts_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_google_storage_v2_ObjectContexts_CustomEntry_descriptor; + static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_google_storage_v2_ObjectContexts_CustomEntry_fieldAccessorTable; static final com.google.protobuf.Descriptors.Descriptor internal_static_google_storage_v2_CustomerEncryption_descriptor; static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable @@ -666,7 +678,7 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { + "\014write_handle\030\003" + " \001(\0132\".google.storage.v2.BidiWriteHandleH\001\210\001\001B\016\n" + "\014write_statusB\017\n\r" - + "_write_handle\"\313\003\n" + + "_write_handle\"\340\003\n" + "\022ListObjectsRequest\0225\n" + "\006parent\030\001 \001(\tB%\340A\002\372A\037\n" + "\035storage.googleapis.com/Bucket\022\026\n" @@ -683,12 +695,13 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { + "\014soft_deleted\030\014 \001(\010B\003\340A\001\022(\n" + "\033include_folders_as_prefixes\030\r" + " \001(\010B\003\340A\001\022\027\n\n" - + "match_glob\030\016 \001(\tB\003\340A\001B\014\n\n" + + "match_glob\030\016 \001(\tB\003\340A\001\022\023\n" + + "\006filter\030\017 \001(\tB\003\340A\001B\014\n\n" + "_read_mask\"\212\001\n" + "\027QueryWriteStatusRequest\022\026\n" + "\tupload_id\030\001 \001(\tB\003\340A\002\022W\n" - + "\034common_object_request_params\030\002 \001(\0132,.goo" - + "gle.storage.v2.CommonObjectRequestParamsB\003\340A\001\"s\n" + + "\034common_object_request_params\030\002" + + " \001(\0132,.google.storage.v2.CommonObjectRequestParamsB\003\340A\001\"s\n" + "\030QueryWriteStatusResponse\022\030\n" + "\016persisted_size\030\001 \001(\003H\000\022-\n" + "\010resource\030\002 \001(\0132\031.google.storage.v2.ObjectH\000B\016\n" @@ -699,7 +712,8 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { + "\035storage.googleapis.com/Bucket\022F\n" + "\023destination_kms_key\030\033 \001(\tB)\340A\001\372A#\n" + "!cloudkms.googleapis.com/CryptoKey\0223\n" - + "\013destination\030\001 \001(\0132\031.google.storage.v2.ObjectB\003\340A\001\022<\n\r" + + "\013destination\030\001 \001(\0132\031.google.storage.v2.ObjectB\003\340A\001\022<\n" + + "\r" + "source_bucket\030\002 \001(\tB%\340A\002\372A\037\n" + "\035storage.googleapis.com/Bucket\022\032\n\r" + "source_object\030\003 \001(\tB\003\340A\002\022\036\n" @@ -720,8 +734,8 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { + " copy_source_encryption_algorithm\030\020 \001(\tB\003\340A\001\022-\n" + " copy_source_encryption_key_bytes\030\025 \001(\014B\003\340A\001\0224\n" + "\'copy_source_encryption_key_sha256_bytes\030\026 \001(\014B\003\340A\001\022W\n" - + "\034common_object_request_params\030\023" - + " \001(\0132,.google.storage.v2.CommonObjectRequestParamsB\003\340A\001\022A\n" + + "\034common_object_request_params\030\023 \001(\0132,.google.s" + + "torage.v2.CommonObjectRequestParamsB\003\340A\001\022A\n" + "\020object_checksums\030\035" + " \001(\0132\".google.storage.v2.ObjectChecksumsB\003\340A\001B\026\n" + "\024_if_generation_matchB\032\n" @@ -767,8 +781,8 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { + "\032StartResumableWriteRequest\022B\n" + "\021write_object_spec\030\001" + " \001(\0132\".google.storage.v2.WriteObjectSpecB\003\340A\002\022W\n" - + "\034common_object_request_params\030\003 \001(\0132,.google" - + ".storage.v2.CommonObjectRequestParamsB\003\340A\001\022A\n" + + "\034common_object_request_params\030\003" + + " \001(\0132,.google.storage.v2.CommonObjectRequestParamsB\003\340A\001\022A\n" + "\020object_checksums\030\005" + " \001(\0132\".google.storage.v2.ObjectChecksumsB\003\340A\001\"0\n" + "\033StartResumableWriteResponse\022\021\n" @@ -825,8 +839,8 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { + "storage_class\030\007 \001(\tB\003\340A\001\022\020\n" + "\003rpo\030\033 \001(\tB\003\340A\001\0228\n" + "\003acl\030\010 \003(\0132&.google.storage.v2.BucketAccessControlB\003\340A\001\022G\n" - + "\022default_object_acl\030\t \003(\0132&" - + ".google.storage.v2.ObjectAccessControlB\003\340A\001\022;\n" + + "\022default_object_acl\030\t" + + " \003(\0132&.google.storage.v2.ObjectAccessControlB\003\340A\001\022;\n" + "\tlifecycle\030\n" + " \001(\0132#.google.storage.v2.Bucket.LifecycleB\003\340A\001\0224\n" + "\013create_time\030\013 \001(\0132\032.google.protobuf.TimestampB\003\340A\003\0221\n" @@ -834,34 +848,34 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { + "\013update_time\030\r" + " \001(\0132\032.google.protobuf.TimestampB\003\340A\003\022%\n" + "\030default_event_based_hold\030\016 \001(\010B\003\340A\001\022:\n" - + "\006labels\030\017 \003(\0132%" - + ".google.storage.v2.Bucket.LabelsEntryB\003\340A\001\0227\n" - + "\007website\030\020" - + " \001(\0132!.google.storage.v2.Bucket.WebsiteB\003\340A\001\022=\n\n" - + "versioning\030\021 \001(\0132" - + "$.google.storage.v2.Bucket.VersioningB\003\340A\001\0227\n" + + "\006labels\030\017" + + " \003(\0132%.google.storage.v2.Bucket.LabelsEntryB\003\340A\001\0227\n" + + "\007website\030\020 \001(\013" + + "2!.google.storage.v2.Bucket.WebsiteB\003\340A\001\022=\n\n" + + "versioning\030\021" + + " \001(\0132$.google.storage.v2.Bucket.VersioningB\003\340A\001\0227\n" + "\007logging\030\022 \001(\0132!.google.storage.v2.Bucket.LoggingB\003\340A\001\022,\n" + "\005owner\030\023 \001(\0132\030.google.storage.v2.OwnerB\003\340A\003\022=\n\n" + "encryption\030\024" + " \001(\0132$.google.storage.v2.Bucket.EncryptionB\003\340A\001\0227\n" + "\007billing\030\025 \001(\0132!.google.storage.v2.Bucket.BillingB\003\340A\001\022H\n" - + "\020retention_policy\030\026" - + " \001(\0132).google.storage.v2.Bucket.RetentionPolicyB\003\340A\001\022<\n\n" - + "iam_config\030\027 \001(\0132" - + "#.google.storage.v2.Bucket.IamConfigB\003\340A\001\022\032\n\r" + + "\020retention_policy\030\026 \001(\0132).googl" + + "e.storage.v2.Bucket.RetentionPolicyB\003\340A\001\022<\n\n" + + "iam_config\030\027" + + " \001(\0132#.google.storage.v2.Bucket.IamConfigB\003\340A\001\022\032\n\r" + "satisfies_pzs\030\031 \001(\010B\003\340A\001\022U\n" - + "\027custom_placement_config\030\032" - + " \001(\0132/.google.storage.v2.Bucket.CustomPlacementConfigB\003\340A\001\022;\n" - + "\tautoclass\030\034" - + " \001(\0132#.google.storage.v2.Bucket.AutoclassB\003\340A\001\022T\n" - + "\026hierarchical_namespace\030 " - + " \001(\0132/.google.storage.v2.Bucket.HierarchicalNamespaceB\003\340A\001\022K\n" - + "\022soft_delete_policy\030\037" - + " \001(\0132*.google.storage.v2.Bucket.SoftDeletePolicyB\003\340A\001\022H\n" + + "\027custom_placement_config\030\032 " + + "\001(\0132/.google.storage.v2.Bucket.CustomPlacementConfigB\003\340A\001\022;\n" + + "\tautoclass\030\034 \001(\0132#.g" + + "oogle.storage.v2.Bucket.AutoclassB\003\340A\001\022T\n" + + "\026hierarchical_namespace\030 \001(\0132/.google." + + "storage.v2.Bucket.HierarchicalNamespaceB\003\340A\001\022K\n" + + "\022soft_delete_policy\030\037 \001(\0132*.googl" + + "e.storage.v2.Bucket.SoftDeletePolicyB\003\340A\001\022H\n" + "\020object_retention\030!" + " \001(\0132).google.storage.v2.Bucket.ObjectRetentionB\003\340A\001\022?\n" - + "\tip_filter\030& \001(\0132\".goog" - + "le.storage.v2.Bucket.IpFilterB\003\340A\001H\000\210\001\001\032&\n" + + "\tip_filter\030&" + + " \001(\0132\".google.storage.v2.Bucket.IpFilterB\003\340A\001H\000\210\001\001\032&\n" + "\007Billing\022\033\n" + "\016requester_pays\030\001 \001(\010B\003\340A\001\032l\n" + "\004Cors\022\023\n" @@ -872,14 +886,16 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { + "Encryption\022B\n" + "\017default_kms_key\030\001 \001(\tB)\340A\001\372A#\n" + "!cloudkms.googleapis.com/CryptoKey\022\215\001\n" - + ",google_managed_encryption_enforcement_config\030\002" - + " \001(\0132M.google.storage.v2.Bucket.Encry" - + "ption.GoogleManagedEncryptionEnforcementConfigB\003\340A\001H\000\210\001\001\022\221\001\n" - + ".customer_managed_en", - "cryption_enforcement_config\030\003 \001(\0132O.google.storage.v2.Bucket.Encryption.Customer" - + "ManagedEncryptionEnforcementConfigB\003\340A\001H\001\210\001\001\022\223\001\n" - + "/customer_supplied_encryption_enforcement_config\030\004 \001(\0132P.google.storage." - + "v2.Bucket.Encryption.CustomerSuppliedEncryptionEnforcementConfigB\003\340A\001H\002\210\001\001\032\252\001\n" + + ",google_managed_encryption_enforcement_config\030\002 \001(\0132M.google.st" + + "orage.v2.Bucket.Encryption.GoogleManaged" + + "EncryptionEnforcementConfigB\003\340A\001H\000\210\001\001\022\221\001", + "\n" + + ".customer_managed_encryption_enforcement_config\030\003" + + " \001(\0132O.google.storage.v2.Bucke" + + "t.Encryption.CustomerManagedEncryptionEnforcementConfigB\003\340A\001H\001\210\001\001\022\223\001\n" + + "/customer_supplied_encryption_enforcement_config\030\004 " + + "\001(\0132P.google.storage.v2.Bucket.Encryptio" + + "n.CustomerSuppliedEncryptionEnforcementConfigB\003\340A\001H\002\210\001\001\032\252\001\n" + "(GoogleManagedEncryptionEnforcementConfig\022\035\n" + "\020restriction_mode\030\003 \001(\tH\000\210\001\001\0227\n" + "\016effective_time\030\002" @@ -902,21 +918,21 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { + "/_customer_managed_encryption_enforcement_configB2\n" + "0_customer_supplied_encryption_enforcement_config\032\200\002\n" + "\tIamConfig\022f\n" - + "\033uniform_bucket_level_access\030\001 \001(" - + "\0132<.google.storage.v2.Bucket.IamConfig.UniformBucketLevelAccessB\003\340A\001\022%\n" + + "\033uniform_bucket_level_access\030\001 \001(\0132<.google.storage." + + "v2.Bucket.IamConfig.UniformBucketLevelAccessB\003\340A\001\022%\n" + "\030public_access_prevention\030\003 \001(\tB\003\340A\001\032d\n" + "\030UniformBucketLevelAccess\022\024\n" + "\007enabled\030\001 \001(\010B\003\340A\001\0222\n" + "\tlock_time\030\002" + " \001(\0132\032.google.protobuf.TimestampB\003\340A\001\032\252\006\n" + "\tLifecycle\022;\n" - + "\004rule\030\001 \003(\0132(." - + "google.storage.v2.Bucket.Lifecycle.RuleB\003\340A\001\032\337\005\n" + + "\004rule\030\001" + + " \003(\0132(.google.storage.v2.Bucket.Lifecycle.RuleB\003\340A\001\032\337\005\n" + "\004Rule\022D\n" - + "\006action\030\001 \001(\0132/.google.s" - + "torage.v2.Bucket.Lifecycle.Rule.ActionB\003\340A\001\022J\n" - + "\tcondition\030\002 \001(\01322.google.storage." - + "v2.Bucket.Lifecycle.Rule.ConditionB\003\340A\001\0327\n" + + "\006action\030\001" + + " \001(\0132/.google.storage.v2.Bucket.Lifecycle.Rule.ActionB\003\340A\001\022J\n" + + "\tcondition\030\002 " + + "\001(\01322.google.storage.v2.Bucket.Lifecycle.Rule.ConditionB\003\340A\001\0327\n" + "\006Action\022\021\n" + "\004type\030\001 \001(\tB\003\340A\001\022\032\n\r" + "storage_class\030\002 \001(\tB\003\340A\001\032\213\004\n" @@ -973,10 +989,10 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { + "#_terminal_storage_class_update_time\032\375\003\n" + "\010IpFilter\022\021\n" + "\004mode\030\001 \001(\tH\000\210\001\001\022Z\n" - + "\025public_network_source\030\002" - + " \001(\01326.google.storage.v2.Bucket.IpFilter.PublicNetworkSourceH\001\210\001\001\022U\n" - + "\023vpc_network_sources\030\003 \003(\01323.google.storag" - + "e.v2.Bucket.IpFilter.VpcNetworkSourceB\003\340A\001\022!\n" + + "\025public_network_source\030\002 \001(\01326.go" + + "ogle.storage.v2.Bucket.IpFilter.PublicNetworkSourceH\001\210\001\001\022U\n" + + "\023vpc_network_sources\030\003" + + " \003(\01323.google.storage.v2.Bucket.IpFilter.VpcNetworkSourceB\003\340A\001\022!\n" + "\024allow_cross_org_vpcs\030\004 \001(\010B\003\340A\001\022+\n" + "\036allow_all_service_agent_access\030\005 \001(\010H\002\210\001\001\032:\n" + "\023PublicNetworkSource\022#\n" @@ -993,8 +1009,8 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { + "\013LabelsEntry\022\013\n" + "\003key\030\001 \001(\t\022\r\n" + "\005value\030\002 \001(\t:\0028\001:X\352AU\n" - + "\035storage.googleapis.com/Bucket\022#proje" - + "cts/{project}/buckets/{bucket}*\007buckets2\006bucketB\014\n\n" + + "\035storage.googlea" + + "pis.com/Bucket\022#projects/{project}/buckets/{bucket}*\007buckets2\006bucketB\014\n\n" + "_ip_filter\"\366\001\n" + "\023BucketAccessControl\022\021\n" + "\004role\030\001 \001(\tB\003\340A\001\022\017\n" @@ -1014,16 +1030,29 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { + "\017ObjectChecksums\022\023\n" + "\006crc32c\030\001 \001(\007H\000\210\001\001\022\025\n" + "\010md5_hash\030\002 \001(\014B\003\340A\001B\t\n" - + "\007_crc32c\"V\n" + + "\007_crc32c\"\234\001\n" + + "\032ObjectCustomContextPayload\022\022\n" + + "\005value\030\001 \001(\tB\003\340A\002\0224\n" + + "\013create_time\030\002 \001(\0132\032.google.protobuf.TimestampB\003\340A\003\0224\n" + + "\013update_time\030\003" + + " \001(\0132\032.google.protobuf.TimestampB\003\340A\003\"\262\001\n" + + "\016ObjectContexts\022B\n" + + "\006custom\030\001 \003(\0132-.goo" + + "gle.storage.v2.ObjectContexts.CustomEntryB\003\340A\001\032\\\n" + + "\013CustomEntry\022\013\n" + + "\003key\030\001 \001(\t\022<\n" + + "\005value\030\002" + + " \001(\0132-.google.storage.v2.ObjectCustomContextPayload:\0028\001\"V\n" + "\022CustomerEncryption\022!\n" + "\024encryption_algorithm\030\001 \001(\tB\003\340A\001\022\035\n" - + "\020key_sha256_bytes\030\003 \001(\014B\003\340A\001\"\327\r\n" + + "\020key_sha256_bytes\030\003 \001(\014B\003\340A\001\"\221\016\n" + "\006Object\022\021\n" + "\004name\030\001 \001(\tB\003\340A\005\0225\n" + "\006bucket\030\002 \001(\tB%\340A\005\372A\037\n" + "\035storage.googleapis.com/Bucket\022\021\n" + "\004etag\030\033 \001(\tB\003\340A\001\022\027\n\n" - + "generation\030\003 \001(\003B\003\340A\005\022\037\n\r" + + "generation\030\003 \001(\003B\003\340A\005\022\037\n" + + "\r" + "restore_token\030# \001(\tB\003\340A\003H\000\210\001\001\022\033\n" + "\016metageneration\030\004 \001(\003B\003\340A\003\022\032\n\r" + "storage_class\030\005 \001(\tB\003\340A\001\022\021\n" @@ -1053,7 +1082,8 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { + "\025retention_expire_time\030\025" + " \001(\0132\032.google.protobuf.TimestampB\003\340A\001\022>\n" + "\010metadata\030\026" - + " \003(\0132\'.google.storage.v2.Object.MetadataEntryB\003\340A\001\022\035\n" + + " \003(\0132\'.google.storage.v2.Object.MetadataEntryB\003\340A\001\0228\n" + + "\010contexts\030& \001(\0132!.google.storage.v2.ObjectContextsB\003\340A\001\022\035\n" + "\020event_based_hold\030\027 \001(\010H\001\210\001\001\022,\n" + "\005owner\030\030 \001(\0132\030.google.storage.v2.OwnerB\003\340A\003\022G\n" + "\023customer_encryption\030\031" @@ -1061,10 +1091,10 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { + "\013custom_time\030\032 \001(\0132\032.google.protobuf.TimestampB\003\340A\001\022>\n" + "\020soft_delete_time\030\034" + " \001(\0132\032.google.protobuf.TimestampB\003\340A\003H\002\210\001\001\022>\n" - + "\020hard_delete_time\030\035 \001(" - + "\0132\032.google.protobuf.TimestampB\003\340A\003H\003\210\001\001\022;\n" - + "\tretention\030\036" - + " \001(\0132#.google.storage.v2.Object.RetentionB\003\340A\001\032\274\001\n" + + "\020hard_delete_time\030\035" + + " \001(\0132\032.google.protobuf.TimestampB\003\340A\003H\003\210\001\001\022;\n" + + "\tretention\030\036 \001(\0132#." + + "google.storage.v2.Object.RetentionB\003\340A\001\032\274\001\n" + "\tRetention\022;\n" + "\004mode\030\001" + " \001(\0162(.google.storage.v2.Object.Retention.ModeB\003\340A\001\022:\n" @@ -1107,98 +1137,96 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { + "\003end\030\002 \001(\003\022\027\n" + "\017complete_length\030\003 \001(\0032\237\037\n" + "\007Storage\022r\n" - + "\014DeleteBucket\022&.goo" - + "gle.storage.v2.DeleteBucketRequest\032\026.google.protobuf.Empty\"\"\332A\004name\212\323\344\223\002\025\022\023\n" + + "\014DeleteBucket\022&.google.storage.v2.Delete" + + "BucketRequest\032\026.google.protobuf.Empty\"\"\332A\004name\212\323\344\223\002\025\022\023\n" + "\004name\022\013{bucket=**}\022o\n" - + "\tGetBucket\022#.google.sto" - + "rage.v2.GetBucketRequest\032\031.google.storage.v2.Bucket\"\"\332A\004name\212\323\344\223\002\025\022\023\n" + + "\tGetBucket\022#.google.storage.v2.GetBucketRequ" + + "est\032\031.google.storage.v2.Bucket\"\"\332A\004name\212\323\344\223\002\025\022\023\n" + "\004name\022\013{bucket=**}\022\253\001\n" - + "\014CreateBucket\022&.google.storage.v2.CreateBucketRequest\032\031.google.storag" - + "e.v2.Bucket\"X\332A\027parent,bucket,bucket_id\212\323\344\223\0028\022\026\n" + + "\014CreateBucket\022&.google.storage.v2.CreateBucketRequ" + + "est\032\031.google.storage.v2.Bucket\"X\332A\027parent,bucket,bucket_id\212\323\344\223\0028\022\026\n" + "\006parent\022\014{project=**}\022\036\n" + "\016bucket.project\022\014{project=**}\022\205\001\n" - + "\013ListBuckets\022%.google.storage.v2.ListBucketsRequest\032&.g" - + "oogle.storage.v2.ListBucketsResponse\"\'\332A\006parent\212\323\344\223\002\030\022\026\n" + + "\013ListBuckets\022%.google.storage.v2.Lis" + + "tBucketsRequest\032&.google.storage.v2.ListBucketsResponse\"\'\332A\006parent\212\323\344\223\002\030\022\026\n" + "\006parent\022\014{project=**}\022\223\001\n" - + "\031LockBucketRetentionPolicy\0223.google.storage.v2.LockBucketRetentionPolicyRequest" - + "\032\031.google.storage.v2.Bucket\"&\332A\006bucket\212\323\344\223\002\027\022\025\n" + + "\031LockBucketRetentionPolicy\0223.google.storage.v2.LockBucketRet" + + "entionPolicyRequest\032\031.google.storage.v2.Bucket\"&\332A\006bucket\212\323\344\223\002\027\022\025\n" + "\006bucket\022\013{bucket=**}\022\243\001\n" - + "\014GetIamPolicy\022\".google.iam.v1.GetIamPolicyRequest" - + "\032\025.google.iam.v1.Policy\"X\332A\010resource\212\323\344\223\002G\022\027\n" + + "\014GetIamPolicy\022\".google.iam.v1." + + "GetIamPolicyRequest\032\025.google.iam.v1.Policy\"X\332A\010resource\212\323\344\223\002G\022\027\n" + "\010resource\022\013{bucket=**}\022,\n" + "\010resource\022 {bucket=projects/*/buckets/*}/**\022\252\001\n" - + "\014SetIamPolicy\022\".google.iam.v1.SetIamPolicyR" - + "equest\032\025.google.iam.v1.Policy\"_\332A\017resource,policy\212\323\344\223\002G\022\027\n" + + "\014SetIamPolicy\022\".google.i" + + "am.v1.SetIamPolicyRequest\032\025.google.iam.v1.Policy\"_\332A\017resource,policy\212\323\344\223\002G\022\027\n" + "\010resource\022\013{bucket=**}\022,\n" + "\010resource\022 {bucket=projects/*/buckets/*}/**\022\226\002\n" - + "\022TestIamPermissions\022(.google.iam.v1.TestIamPermissionsRequest\032).google" - + ".iam.v1.TestIamPermissionsResponse\"\252\001\332A\024resource,permissions\212\323\344\223\002\214\001\022\027\n" + + "\022TestIamPermissions\022(.google.iam.v1.TestIamPermissi" + + "onsRequest\032).google.iam.v1.TestIamPermis" + + "sionsResponse\"\252\001\332A\024resource,permissions\212\323\344\223\002\214\001\022\027\n" + "\010resource\022\013{bucket=**}\0224\n" + "\010resource\022({bucket=projects/*/buckets/*}/objects/**\022;\n" + "\010resource\022/{bucket=projects/*/buckets/*}/managedFolders/**\022\212\001\n" - + "\014UpdateBucket\022&.google.storage.v2.UpdateBucketRequest\032\031.google.storag" - + "e.v2.Bucket\"7\332A\022bucket,update_mask\212\323\344\223\002\034\022\032\n" + + "\014UpdateBucket\022&.google.storage.v2.UpdateBucketRequ" + + "est\032\031.google.storage.v2.Bucket\"7\332A\022bucket,update_mask\212\323\344\223\002\034\022\032\n" + "\013bucket.name\022\013{bucket=**}\022~\n\r" - + "ComposeObject\022\'.google.storage.v2.ComposeObjectR" - + "equest\032\031.google.storage.v2.Object\")\212\323\344\223\002#\022!\n" + + "ComposeObject\022\'.google.storag" + + "e.v2.ComposeObjectRequest\032\031.google.storage.v2.Object\")\212\323\344\223\002#\022!\n" + "\022destination.bucket\022\013{bucket=**}\022\230\001\n" - + "\014DeleteObject\022&.google.storage.v2.Delete" - + "ObjectRequest\032\026.google.protobuf.Empty\"H\332A\r" + + "\014DeleteObject\022&.googl" + + "e.storage.v2.DeleteObjectRequest\032\026.google.protobuf.Empty\"H\332A\r" + "bucket,object\332A\030bucket,object,generation\212\323\344\223\002\027\022\025\n" + "\006bucket\022\013{bucket=**}\022\215\001\n\r" - + "RestoreObject\022\'.google.storage.v2.RestoreObj" - + "ectRequest\032\031.google.storage.v2.Object\"8\332A\030bucket,object,generation\212\323\344\223\002\027\022\025\n" + + "RestoreObject\022\'.google.storage.v2.RestoreObjectRequest\032\031.google.s" + + "torage.v2.Object\"8\332A\030bucket,object,generation\212\323\344\223\002\027\022\025\n" + "\006bucket\022\013{bucket=**}\022\272\001\n" - + "\024CancelResumableWrite\022..google.storage.v2.CancelResumableWrit" - + "eRequest\032/.google.storage.v2.CancelResumableWriteResponse\"A\332A" - + "\tupload_id\212\323\344\223\002/\022-\n" + + "\024CancelResumableWrite\022..google.storage.v2." + + "CancelResumableWriteRequest\032/.google.sto" + + "rage.v2.CancelResumableWriteResponse\"A\332A\tupload_id\212\323\344\223\002/\022-\n" + "\tupload_id\022 {bucket=projects/*/buckets/*}/**\022\225\001\n" - + "\tGetObject\022#.google.storage.v2.G" - + "etObjectRequest\032\031.google.storage.v2.Object\"H\332A\r" + + "\tGetObject\022#." + + "google.storage.v2.GetObjectRequest\032\031.google.storage.v2.Object\"H\332A\r" + "bucket,object\332A\030bucket,object,generation\212\323\344\223\002\027\022\025\n" - + "\006bucket\022\013{bucket=**}\022\245\001\n" - + "\n" - + "ReadObject\022$.google.storage.v2.ReadObje" - + "ctRequest\032%.google.storage.v2.ReadObjectResponse\"H\332A\r" + + "\006bucket\022\013{bucket=**}\022\245\001\n\n" + + "ReadObject\022$.google." + + "storage.v2.ReadObjectRequest\032%.google.storage.v2.ReadObjectResponse\"H\332A\r" + "bucket,object\332A\030bucket,object,generation\212\323\344\223\002\027\022\025\n" + "\006bucket\022\013{bucket=**}0\001\022\231\001\n" - + "\016BidiReadObject\022(.google.storage" - + ".v2.BidiReadObjectRequest\032).google.storage.v2.BidiReadObjectResponse\".\212\323\344\223\002(\022&\n" + + "\016BidiReadObject\022(.google.storage.v2.BidiReadObjectReq" + + "uest\032).google.storage.v2.BidiReadObjectResponse\".\212\323\344\223\002(\022&\n" + "\027read_object_spec.bucket\022\013{bucket=**}(\0010\001\022\214\001\n" - + "\014UpdateObject\022&.google.storage.v2.Up" - + "dateObjectRequest\032\031.google.storage.v2.Object\"9\332A\022object,update_mask\212\323\344\223\002\036\022\034\n\r" + + "\014UpdateObject\022&.google.storage.v2.UpdateObjectRequest\032\031.g" + + "oogle.storage.v2.Object\"9\332A\022object,update_mask\212\323\344\223\002\036\022\034\n\r" + "object.bucket\022\013{bucket=**}\022`\n" - + "\013WriteObject\022%.google.storage.v2.WriteObjectRequest\032&." - + "google.storage.v2.WriteObjectResponse\"\000(\001\022n\n" - + "\017BidiWriteObject\022).google.storage.v2" - + ".BidiWriteObjectRequest\032*.google.storage.v2.BidiWriteObjectResponse\"\000(\0010\001\022\204\001\n" - + "\013ListObjects\022%.google.storage.v2.ListObject" - + "sRequest\032&.google.storage.v2.ListObjectsResponse\"&\332A\006parent\212\323\344\223\002\027\022\025\n" + + "\013WriteObject\022%.google.storage.v2.Wr" + + "iteObjectRequest\032&.google.storage.v2.WriteObjectResponse\"\000(\001\022n\n" + + "\017BidiWriteObject\022).google.storage.v2.BidiWriteObjectReque" + + "st\032*.google.storage.v2.BidiWriteObjectResponse\"\000(\0010\001\022\204\001\n" + + "\013ListObjects\022%.google.storage.v2.ListObjectsRequest\032&.google.sto" + + "rage.v2.ListObjectsResponse\"&\332A\006parent\212\323\344\223\002\027\022\025\n" + "\006parent\022\013{bucket=**}\022\230\001\n\r" - + "RewriteObject\022\'.google.stor" - + "age.v2.RewriteObjectRequest\032\".google.storage.v2.RewriteResponse\":\212\323\344\223\0024\022\017\n\r" + + "RewriteObject\022\'.google.storage.v2.RewriteObjectR" + + "equest\032\".google.storage.v2.RewriteResponse\":\212\323\344\223\0024\022\017\n\r" + "source_bucket\022!\n" + "\022destination_bucket\022\013{bucket=**}\022\256\001\n" - + "\023StartResumableWrite\022-.google.storage.v2.StartResumableWriteRequest\032..goo" - + "gle.storage.v2.StartResumableWriteResponse\"8\212\323\344\223\0022\0220\n" + + "\023StartResumableWrite\022-.google.storage.v2.StartResumabl" + + "eWriteRequest\032..google.storage.v2.StartResumableWriteResponse\"8\212\323\344\223\0022\0220\n" + "!write_object_spec.resource.bucket\022\013{bucket=**}\022\256\001\n" - + "\020QueryWriteStatus\022*.google.storage.v2.QueryWriteStatusRe" - + "quest\032+.google.storage.v2.QueryWriteStatusResponse\"A\332A" + + "\020QueryWriteStatus\022*.google.storage.v2" + + ".QueryWriteStatusRequest\032+.google.storage.v2.QueryWriteStatusResponse\"A\332A" + "\tupload_id\212\323\344\223\002/\022-\n" + "\tupload_id\022 {bucket=projects/*/buckets/*}/**\022\226\001\n\n" - + "MoveObject\022$.google.storage.v2.MoveObj" - + "ectRequest\032\031.google.storage.v2.Object\"G\332" - + "A\'bucket,source_object,destination_object\212\323\344\223\002\027\022\025\n" - + "\006bucket\022\013{bucket=**}\032\247\002\312A\026stor" - + "age.googleapis.com\322A\212\002https://www.google" - + "apis.com/auth/cloud-platform,https://www.googleapis.com/auth/cloud-platform.read" - + "-only,https://www.googleapis.com/auth/devstorage.full_control,https://www.google" - + "apis.com/auth/devstorage.read_only,https" - + "://www.googleapis.com/auth/devstorage.read_writeB\342\001\n" - + "\025com.google.storage.v2B\014Stor" - + "ageProtoP\001Z>cloud.google.com/go/storage/internal/apiv2/storagepb;storagepb\352Ax\n" - + "!cloudkms.googleapis.com/CryptoKey\022Sprojects/{project}/locations/{location}/keyRin" - + "gs/{key_ring}/cryptoKeys/{crypto_key}b\006proto3" + + "MoveObject\022$.google.storage.v2.MoveObjectRequest\032\031.google.s" + + "torage.v2.Object\"G\332A\'bucket,source_object,destination_object\212\323\344\223\002\027\022\025\n" + + "\006bucket\022\013{bucket=**}\032\247\002\312A\026storage.googleapis.com\322A\212" + + "\002https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/" + + "cloud-platform.read-only,https://www.googleapis.com/auth/devstorage.full_control" + + ",https://www.googleapis.com/auth/devstor" + + "age.read_only,https://www.googleapis.com/auth/devstorage.read_writeB\342\001\n" + + "\025com.google.storage.v2B\014StorageProtoP\001Z>cloud.goo" + + "gle.com/go/storage/internal/apiv2/storagepb;storagepb\352Ax\n" + + "!cloudkms.googleapis.com/CryptoKey\022Sprojects/{project}/location" + + "s/{location}/keyRings/{key_ring}/cryptoKeys/{crypto_key}b\006proto3" }; descriptor = com.google.protobuf.Descriptors.FileDescriptor.internalBuildGeneratedFileFrom( @@ -1603,6 +1631,7 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { "SoftDeleted", "IncludeFoldersAsPrefixes", "MatchGlob", + "Filter", }); internal_static_google_storage_v2_QueryWriteStatusRequest_descriptor = getDescriptor().getMessageTypes().get(33); @@ -2009,15 +2038,39 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { new java.lang.String[] { "Crc32C", "Md5Hash", }); - internal_static_google_storage_v2_CustomerEncryption_descriptor = + internal_static_google_storage_v2_ObjectCustomContextPayload_descriptor = getDescriptor().getMessageTypes().get(47); + internal_static_google_storage_v2_ObjectCustomContextPayload_fieldAccessorTable = + new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_google_storage_v2_ObjectCustomContextPayload_descriptor, + new java.lang.String[] { + "Value", "CreateTime", "UpdateTime", + }); + internal_static_google_storage_v2_ObjectContexts_descriptor = + getDescriptor().getMessageTypes().get(48); + internal_static_google_storage_v2_ObjectContexts_fieldAccessorTable = + new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_google_storage_v2_ObjectContexts_descriptor, + new java.lang.String[] { + "Custom", + }); + internal_static_google_storage_v2_ObjectContexts_CustomEntry_descriptor = + internal_static_google_storage_v2_ObjectContexts_descriptor.getNestedTypes().get(0); + internal_static_google_storage_v2_ObjectContexts_CustomEntry_fieldAccessorTable = + new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_google_storage_v2_ObjectContexts_CustomEntry_descriptor, + new java.lang.String[] { + "Key", "Value", + }); + internal_static_google_storage_v2_CustomerEncryption_descriptor = + getDescriptor().getMessageTypes().get(49); internal_static_google_storage_v2_CustomerEncryption_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( internal_static_google_storage_v2_CustomerEncryption_descriptor, new java.lang.String[] { "EncryptionAlgorithm", "KeySha256Bytes", }); - internal_static_google_storage_v2_Object_descriptor = getDescriptor().getMessageTypes().get(48); + internal_static_google_storage_v2_Object_descriptor = getDescriptor().getMessageTypes().get(50); internal_static_google_storage_v2_Object_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( internal_static_google_storage_v2_Object_descriptor, @@ -2047,6 +2100,7 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { "TemporaryHold", "RetentionExpireTime", "Metadata", + "Contexts", "EventBasedHold", "Owner", "CustomerEncryption", @@ -2072,7 +2126,7 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { "Key", "Value", }); internal_static_google_storage_v2_ObjectAccessControl_descriptor = - getDescriptor().getMessageTypes().get(49); + getDescriptor().getMessageTypes().get(51); internal_static_google_storage_v2_ObjectAccessControl_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( internal_static_google_storage_v2_ObjectAccessControl_descriptor, @@ -2088,7 +2142,7 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { "ProjectTeam", }); internal_static_google_storage_v2_ListObjectsResponse_descriptor = - getDescriptor().getMessageTypes().get(50); + getDescriptor().getMessageTypes().get(52); internal_static_google_storage_v2_ListObjectsResponse_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( internal_static_google_storage_v2_ListObjectsResponse_descriptor, @@ -2096,14 +2150,14 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { "Objects", "Prefixes", "NextPageToken", }); internal_static_google_storage_v2_ProjectTeam_descriptor = - getDescriptor().getMessageTypes().get(51); + getDescriptor().getMessageTypes().get(53); internal_static_google_storage_v2_ProjectTeam_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( internal_static_google_storage_v2_ProjectTeam_descriptor, new java.lang.String[] { "ProjectNumber", "Team", }); - internal_static_google_storage_v2_Owner_descriptor = getDescriptor().getMessageTypes().get(52); + internal_static_google_storage_v2_Owner_descriptor = getDescriptor().getMessageTypes().get(54); internal_static_google_storage_v2_Owner_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( internal_static_google_storage_v2_Owner_descriptor, @@ -2111,7 +2165,7 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { "Entity", "EntityId", }); internal_static_google_storage_v2_ContentRange_descriptor = - getDescriptor().getMessageTypes().get(53); + getDescriptor().getMessageTypes().get(55); internal_static_google_storage_v2_ContentRange_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( internal_static_google_storage_v2_ContentRange_descriptor, diff --git a/proto-google-cloud-storage-v2/src/main/proto/google/storage/v2/storage.proto b/proto-google-cloud-storage-v2/src/main/proto/google/storage/v2/storage.proto index a69e996f8..cb677d47d 100644 --- a/proto-google-cloud-storage-v2/src/main/proto/google/storage/v2/storage.proto +++ b/proto-google-cloud-storage-v2/src/main/proto/google/storage/v2/storage.proto @@ -1504,6 +1504,11 @@ message ListObjectsRequest { // Glob](https://cloud.google.com/storage/docs/json_api/v1/objects/list#list-objects-and-prefixes-using-glob) // for the full syntax. string match_glob = 14 [(google.api.field_behavior) = OPTIONAL]; + + // Optional. Filter the returned objects. Currently only supported for the + // `contexts` field. If `delimiter` is set, the returned `prefixes` are exempt + // from this filter. + string filter = 15 [(google.api.field_behavior) = OPTIONAL]; } // Request object for `QueryWriteStatus`. @@ -2635,6 +2640,27 @@ message ObjectChecksums { bytes md5_hash = 2 [(google.api.field_behavior) = OPTIONAL]; } +// The payload of a single user-defined object context. +message ObjectCustomContextPayload { + // Required. The value of the object context. + string value = 1 [(google.api.field_behavior) = REQUIRED]; + + // Output only. The time at which the object context was created. + google.protobuf.Timestamp create_time = 2 + [(google.api.field_behavior) = OUTPUT_ONLY]; + + // Output only. The time at which the object context was last updated. + google.protobuf.Timestamp update_time = 3 + [(google.api.field_behavior) = OUTPUT_ONLY]; +} + +// All contexts of an object grouped by type. +message ObjectContexts { + // Optional. User-defined object contexts. + map custom = 1 + [(google.api.field_behavior) = OPTIONAL]; +} + // Describes the Customer-Supplied Encryption Key mechanism used to store an // Object's data at rest. message CustomerEncryption { @@ -2817,6 +2843,11 @@ message Object { // Optional. User-provided metadata, in key/value pairs. map metadata = 22 [(google.api.field_behavior) = OPTIONAL]; + // Optional. User-defined or system-defined object contexts. Each object + // context is a key-payload pair, where the key provides the identification + // and the payload holds the associated value and additional metadata. + ObjectContexts contexts = 38 [(google.api.field_behavior) = OPTIONAL]; + // Whether an object is under event-based hold. // An event-based hold is a way to force the retention of an object until // after some event occurs. Once the hold is released by explicitly setting From 6dcd06a73546e8d83e7a66019aaa489416b4e622 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 21 Jul 2025 19:30:32 +0200 Subject: [PATCH 05/15] chore(deps): update storage release dependencies (#3193) --- samples/install-without-bom/pom.xml | 6 +++--- samples/snippets/pom.xml | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml index 2769ffaf0..73c354cb0 100644 --- a/samples/install-without-bom/pom.xml +++ b/samples/install-without-bom/pom.xml @@ -30,12 +30,12 @@ com.google.cloud google-cloud-storage - 2.53.2 + 2.53.3 com.google.cloud google-cloud-storage-control - 2.53.2 + 2.53.3 @@ -78,7 +78,7 @@ com.google.cloud google-cloud-storage - 2.53.2 + 2.53.3 tests test diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml index 2eac738b3..ee1c18863 100644 --- a/samples/snippets/pom.xml +++ b/samples/snippets/pom.xml @@ -31,7 +31,7 @@ com.google.cloud libraries-bom - 26.63.0 + 26.64.0 pom import @@ -99,7 +99,7 @@ com.google.cloud google-cloud-storage - 2.53.2 + 2.53.3 tests test From 9900f8de43b3f2494e19da7d7d6efa5820be72cc Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 21 Jul 2025 19:30:57 +0200 Subject: [PATCH 06/15] test(deps): update dependency org.junit:junit-bom to v5.13.4 (#3199) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f909ec579..41a8badea 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ org.junit junit-bom - 5.13.3 + 5.13.4 pom import From 6ba56e5a4b86a75a9f48beccf79ff6d5fdd3e19f Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 21 Jul 2025 19:31:29 +0200 Subject: [PATCH 07/15] deps: update googleapis/sdk-platform-java action to v2.60.1 (#3196) --- .github/workflows/hermetic_library_generation.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/hermetic_library_generation.yaml b/.github/workflows/hermetic_library_generation.yaml index b984ab43a..4ce1c236a 100644 --- a/.github/workflows/hermetic_library_generation.yaml +++ b/.github/workflows/hermetic_library_generation.yaml @@ -43,7 +43,7 @@ jobs: with: fetch-depth: 0 token: ${{ secrets.CLOUD_JAVA_BOT_TOKEN }} - - uses: googleapis/sdk-platform-java/.github/scripts@v2.59.0 + - uses: googleapis/sdk-platform-java/.github/scripts@v2.60.1 if: env.SHOULD_RUN == 'true' with: base_ref: ${{ github.base_ref }} From 782c3c416583704a196b17f23e9c12c33659f67d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 23 Jul 2025 17:39:16 +0200 Subject: [PATCH 08/15] deps: update dependency com.google.cloud:sdk-platform-java-config to v3.50.2 (#3201) --- .github/workflows/unmanaged_dependency_check.yaml | 2 +- google-cloud-storage-bom/pom.xml | 2 +- pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/unmanaged_dependency_check.yaml b/.github/workflows/unmanaged_dependency_check.yaml index ae89421b7..306521d4e 100644 --- a/.github/workflows/unmanaged_dependency_check.yaml +++ b/.github/workflows/unmanaged_dependency_check.yaml @@ -17,6 +17,6 @@ jobs: # repository .kokoro/build.sh - name: Unmanaged dependency check - uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.50.1 + uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.50.2 with: bom-path: google-cloud-storage-bom/pom.xml diff --git a/google-cloud-storage-bom/pom.xml b/google-cloud-storage-bom/pom.xml index 0c9198ddf..0d51f2f59 100644 --- a/google-cloud-storage-bom/pom.xml +++ b/google-cloud-storage-bom/pom.xml @@ -24,7 +24,7 @@ com.google.cloud sdk-platform-java-config - 3.50.1 + 3.50.2 diff --git a/pom.xml b/pom.xml index 41a8badea..e3c258336 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ com.google.cloud sdk-platform-java-config - 3.50.1 + 3.50.2 From 18978e4ec54790df2939490ef76fc19b9f72eb04 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 23 Jul 2025 17:40:40 +0200 Subject: [PATCH 09/15] deps: update dependency com.google.apis:google-api-services-storage to v1-rev20250718-2.0.0 (#3203) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e3c258336..072cdcb17 100644 --- a/pom.xml +++ b/pom.xml @@ -87,7 +87,7 @@ com.google.apis google-api-services-storage - v1-rev20250629-2.0.0 + v1-rev20250718-2.0.0 com.google.cloud From 14a91ec208067e6afc55923cffda5f69aa33d8b4 Mon Sep 17 00:00:00 2001 From: BenWhitehead Date: Wed, 23 Jul 2025 12:08:47 -0400 Subject: [PATCH 10/15] feat: add BucketInfo.IpFilter (#3177) --- .../clirr-ignored-differences.xml | 6 + .../java/com/google/cloud/storage/Bucket.java | 12 + .../com/google/cloud/storage/BucketInfo.java | 466 +++++++++++++++++- .../google/cloud/storage/GrpcConversions.java | 85 +++- .../google/cloud/storage/JsonConversions.java | 74 +++ .../com/google/cloud/storage/Storage.java | 8 +- .../com/google/cloud/storage/UnifiedOpts.java | 1 + .../storage/it/ITBucketReadMaskTest.java | 1 + .../storage/it/ITOptionRegressionTest.java | 22 +- .../jqwik/BucketArbitraryProvider.java | 5 +- .../storage/jqwik/StorageArbitraries.java | 77 +++ 11 files changed, 742 insertions(+), 15 deletions(-) diff --git a/google-cloud-storage/clirr-ignored-differences.xml b/google-cloud-storage/clirr-ignored-differences.xml index 76929f11f..9acc213a1 100644 --- a/google-cloud-storage/clirr-ignored-differences.xml +++ b/google-cloud-storage/clirr-ignored-differences.xml @@ -139,4 +139,10 @@ * validate(*) + + 7013 + com/google/cloud/storage/BucketInfo$Builder + com.google.cloud.storage.BucketInfo$Builder setIpFilter(com.google.cloud.storage.BucketInfo$IpFilter) + + diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java index 7d25cde12..04fae5d3b 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java @@ -759,6 +759,12 @@ public Builder setHierarchicalNamespace(HierarchicalNamespace hierarchicalNamesp return this; } + @Override + public Builder setIpFilter(IpFilter ipFilter) { + infoBuilder.setIpFilter(ipFilter); + return this; + } + @Override public Bucket build() { return new Bucket(storage, infoBuilder); @@ -943,6 +949,12 @@ Builder clearCustomPlacementConfig() { infoBuilder.clearCustomPlacementConfig(); return this; } + + @Override + Builder clearIpFilter() { + infoBuilder.clearIpFilter(); + return this; + } } Bucket(Storage storage, BucketInfo.BuilderImpl infoBuilder) { diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java index 3899c703a..9762251b0 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java @@ -56,6 +56,7 @@ import java.util.function.Predicate; import java.util.logging.Logger; import java.util.stream.Stream; +import javax.annotation.concurrent.Immutable; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -123,6 +124,7 @@ public class BucketInfo implements Serializable { private final HierarchicalNamespace hierarchicalNamespace; private final SoftDeletePolicy softDeletePolicy; + private final @Nullable IpFilter ipFilter; private final transient ImmutableSet modifiedFields; @@ -1654,6 +1656,432 @@ public boolean isLive() { } } + /** + * A buckets IP + * filtering configuration. Specifies the network sources that can access the bucket, as well + * as its underlying objects. + * + * @since 2.54.0 + */ + @Immutable + public static final class IpFilter implements Serializable { + private static final long serialVersionUID = 3883696370256011372L; + private final @Nullable String mode; + private final @Nullable PublicNetworkSource publicNetworkSource; + private final @Nullable List vpcNetworkSources; + private final @Nullable Boolean allowCrossOrgVpcs; + private final @Nullable Boolean allowAllServiceAgentAccess; + + private IpFilter( + @Nullable String mode, + @Nullable PublicNetworkSource publicNetworkSource, + @Nullable List vpcNetworkSources, + @Nullable Boolean allowCrossOrgVpcs, + @Nullable Boolean allowAllServiceAgentAccess) { + this.mode = mode; + this.publicNetworkSource = publicNetworkSource; + this.vpcNetworkSources = vpcNetworkSources; + this.allowCrossOrgVpcs = allowCrossOrgVpcs; + this.allowAllServiceAgentAccess = allowAllServiceAgentAccess; + } + + /** + * The state of the IP filter configuration. Valid values are `Enabled` and `Disabled`. When set + * to `Enabled`, IP filtering rules are applied to a bucket and all incoming requests to the + * bucket are evaluated against these rules. When set to `Disabled`, IP filtering rules are not + * applied to a bucket. + * + * @since 2.54.0 + * @see Builder#setMode + */ + public @Nullable String getMode() { + return mode; + } + + /** + * Optional. Public IPs allowed to operate or access the bucket. + * + * @since 2.54.0 + * @see Builder#setPublicNetworkSource(PublicNetworkSource) + */ + public @Nullable PublicNetworkSource getPublicNetworkSource() { + return publicNetworkSource; + } + + /** + * Optional. The list of network sources that are allowed to access operations on the bucket or + * the underlying objects. + * + * @since 2.54.0 + * @see Builder#setVpcNetworkSources(List) + */ + public @Nullable List getVpcNetworkSources() { + return vpcNetworkSources; + } + + /** + * Optional. Whether or not to allow VPCs from orgs different than the bucket's parent org to + * access the bucket. When set to true, validations on the existence of the VPCs won't be + * performed. If set to false, each VPC network source will be checked to belong to the same org + * as the bucket as well as validated for existence. + * + * @since 2.54.0 + * @see Builder#setAllowCrossOrgVpcs(Boolean) + */ + public @Nullable Boolean getAllowCrossOrgVpcs() { + return allowCrossOrgVpcs; + } + + /** + * Whether or not to allow all P4SA access to the bucket. When set to true, IP filter config + * validation will not apply. + * + * @since 2.54.0 + * @see Builder#setAllowAllServiceAgentAccess(Boolean) + */ + public @Nullable Boolean getAllowAllServiceAgentAccess() { + return allowAllServiceAgentAccess; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof IpFilter)) { + return false; + } + IpFilter ipFilter = (IpFilter) o; + return Objects.equals(mode, ipFilter.mode) + && Objects.equals(publicNetworkSource, ipFilter.publicNetworkSource) + && Objects.equals(vpcNetworkSources, ipFilter.vpcNetworkSources) + && Objects.equals(allowCrossOrgVpcs, ipFilter.allowCrossOrgVpcs) + && Objects.equals(allowAllServiceAgentAccess, ipFilter.allowAllServiceAgentAccess); + } + + @Override + public int hashCode() { + return Objects.hash( + mode, + publicNetworkSource, + vpcNetworkSources, + allowCrossOrgVpcs, + allowAllServiceAgentAccess); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("mode", mode) + .add("publicNetworkSource", publicNetworkSource) + .add("vpcNetworkSources", vpcNetworkSources) + .add("allowCrossOrgVpcs", allowCrossOrgVpcs) + .add("allowAllServiceAgentAccess", allowAllServiceAgentAccess) + .toString(); + } + + /** + * @since 2.54.0 + */ + public Builder toBuilder() { + return new Builder(this); + } + + /** + * @since 2.54.0 + */ + public static Builder newBuilder() { + return new Builder(); + } + + /** + * @since 2.54.0 + */ + public static final class Builder { + private @Nullable String mode; + private @Nullable PublicNetworkSource publicNetworkSource; + private @Nullable List vpcNetworkSources; + private @Nullable Boolean allowCrossOrgVpcs; + private @Nullable Boolean allowAllServiceAgentAccess; + + private Builder() {} + + private Builder(IpFilter ipFilter) { + this.mode = ipFilter.mode; + this.publicNetworkSource = ipFilter.publicNetworkSource; + this.vpcNetworkSources = ipFilter.vpcNetworkSources; + this.allowCrossOrgVpcs = ipFilter.allowCrossOrgVpcs; + this.allowAllServiceAgentAccess = ipFilter.allowAllServiceAgentAccess; + } + + /** + * The state of the IP filter configuration. Valid values are `Enabled` and `Disabled`. When + * set to `Enabled`, IP filtering rules are applied to a bucket and all incoming requests to + * the bucket are evaluated against these rules. When set to `Disabled`, IP filtering rules + * are not applied to a bucket. + * + * @since 2.54.0 + * @see IpFilter#getMode + */ + public Builder setMode(@Nullable String mode) { + this.mode = mode; + return this; + } + + /** + * Optional. Public IPs allowed to operate or access the bucket. + * + * @since 2.54.0 + * @see IpFilter#getPublicNetworkSource() + */ + public Builder setPublicNetworkSource(@Nullable PublicNetworkSource publicNetworkSource) { + this.publicNetworkSource = publicNetworkSource; + return this; + } + + /** + * Optional. The list of network sources that are allowed to access operations on the bucket + * or the underlying objects. + * + * @since 2.54.0 + * @see IpFilter#getVpcNetworkSources() + */ + public Builder setVpcNetworkSources(@Nullable List vpcNetworkSources) { + this.vpcNetworkSources = vpcNetworkSources; + return this; + } + + /** + * Optional. Whether or not to allow VPCs from orgs different than the bucket's parent org to + * access the bucket. When set to true, validations on the existence of the VPCs won't be + * performed. If set to false, each VPC network source will be checked to belong to the same + * org as the bucket as well as validated for existence. + * + * @since 2.54.0 + * @see IpFilter#getAllowCrossOrgVpcs() + */ + public Builder setAllowCrossOrgVpcs(@Nullable Boolean allowCrossOrgVpcs) { + this.allowCrossOrgVpcs = allowCrossOrgVpcs; + return this; + } + + /** + * Whether or not to allow all P4SA access to the bucket. When set to true, IP filter config + * validation will not apply. + * + * @since 2.54.0 + * @see IpFilter#getAllowAllServiceAgentAccess() + */ + public Builder setAllowAllServiceAgentAccess(@Nullable Boolean allowAllServiceAgentAccess) { + this.allowAllServiceAgentAccess = allowAllServiceAgentAccess; + return this; + } + + /** + * @since 2.54.0 + */ + public IpFilter build() { + return new IpFilter( + mode, + publicNetworkSource, + vpcNetworkSources, + allowCrossOrgVpcs, + allowAllServiceAgentAccess); + } + } + + /** + * The public network IP address ranges that can access the bucket and its data. + * + * @since 2.54.0 + */ + @Immutable + public static final class PublicNetworkSource implements Serializable { + private static final long serialVersionUID = -5597599591237060501L; + + private final List allowedIpCidrRanges; + + private PublicNetworkSource(List allowedIpCidrRanges) { + this.allowedIpCidrRanges = allowedIpCidrRanges; + } + + /** + * Optional. The list of IPv4 and IPv6 cidr blocks that are allowed to operate or access the + * bucket and its underlying objects. + * + * @since 2.54.0 + */ + public List getAllowedIpCidrRanges() { + return allowedIpCidrRanges; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof PublicNetworkSource)) { + return false; + } + PublicNetworkSource that = (PublicNetworkSource) o; + return Objects.equals(allowedIpCidrRanges, that.allowedIpCidrRanges); + } + + @Override + public int hashCode() { + return Objects.hashCode(allowedIpCidrRanges); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("allowedIpCidrRanges", allowedIpCidrRanges) + .toString(); + } + + /** + * @since 2.54.0 + */ + public static PublicNetworkSource of(List allowedIpCidrRanges) { + return new PublicNetworkSource(allowedIpCidrRanges); + } + } + + /** + * The list of VPC networks that can access the bucket. + * + * @since 2.54.0 + */ + @Immutable + public static final class VpcNetworkSource implements Serializable { + private static final long serialVersionUID = 9075759536253054803L; + private final @Nullable String network; + private final @Nullable List allowedIpCidrRanges; + + private VpcNetworkSource( + @Nullable String network, @Nullable List allowedIpCidrRanges) { + this.network = network; + this.allowedIpCidrRanges = allowedIpCidrRanges; + } + + /** + * Name of the network. + * + *

Format: `projects/PROJECT_ID/global/networks/NETWORK_NAME` + * + * @since 2.54.0 + * @see Builder#setNetwork(String) + */ + public @Nullable String getNetwork() { + return network; + } + + /** + * Optional. The list of public or private IPv4 and IPv6 CIDR ranges that can access the + * bucket. In the CIDR IP address block, the specified IP address must be properly truncated, + * meaning all the host bits must be zero or else the input is considered malformed. For + * example, `192.0.2.0/24` is accepted but `192.0.2.1/24` is not. Similarly, for IPv6, + * `2001:db8::/32` is accepted whereas `2001:db8::1/32` is not. + * + * @since 2.54.0 + * @see Builder#setAllowedIpCidrRanges(List) + */ + public @Nullable List getAllowedIpCidrRanges() { + return allowedIpCidrRanges; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof VpcNetworkSource)) { + return false; + } + VpcNetworkSource that = (VpcNetworkSource) o; + return Objects.equals(network, that.network) + && Objects.equals(allowedIpCidrRanges, that.allowedIpCidrRanges); + } + + @Override + public int hashCode() { + return Objects.hash(network, allowedIpCidrRanges); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("network", network) + .add("allowedIpCidrRanges", allowedIpCidrRanges) + .toString(); + } + + /** + * @since 2.54.0 + */ + public Builder toBuilder() { + return new Builder(this); + } + + /** + * @since 2.54.0 + */ + public static Builder newBuilder() { + return new Builder(); + } + + /** + * @since 2.54.0 + */ + public static final class Builder { + private @Nullable String network; + private @Nullable List allowedIpCidrRanges; + + private Builder() {} + + public Builder(VpcNetworkSource vpcNetworksource) { + this.network = vpcNetworksource.network; + this.allowedIpCidrRanges = vpcNetworksource.allowedIpCidrRanges; + } + + /** + * Name of the network. + * + *

Format: `projects/PROJECT_ID/global/networks/NETWORK_NAME` + * + * @since 2.54.0 + * @see VpcNetworkSource#getNetwork() + */ + public Builder setNetwork(@Nullable String network) { + this.network = network; + return this; + } + + /** + * Optional. The list of public or private IPv4 and IPv6 CIDR ranges that can access the + * bucket. In the CIDR IP address block, the specified IP address must be properly + * truncated, meaning all the host bits must be zero or else the input is considered + * malformed. For example, `192.0.2.0/24` is accepted but `192.0.2.1/24` is not. Similarly, + * for IPv6, `2001:db8::/32` is accepted whereas `2001:db8::1/32` is not. + * + * @since 2.54.0 + * @see VpcNetworkSource#getAllowedIpCidrRanges() + */ + public Builder setAllowedIpCidrRanges(@Nullable List allowedIpCidrRanges) { + this.allowedIpCidrRanges = allowedIpCidrRanges; + return this; + } + + /** + * @since 2.54.0 + */ + public VpcNetworkSource build() { + return new VpcNetworkSource(network, allowedIpCidrRanges); + } + } + } + } + /** Builder for {@code BucketInfo}. */ public abstract static class Builder { Builder() {} @@ -1857,6 +2285,11 @@ public Builder setRetentionPeriodDuration(Duration retentionPeriod) { public abstract Builder setSoftDeletePolicy(SoftDeletePolicy softDeletePolicy); + /** + * @since 2.54.0 + */ + public abstract Builder setIpFilter(IpFilter ipFilter); + /** Creates a {@code BucketInfo} object. */ public abstract BucketInfo build(); @@ -1919,6 +2352,8 @@ public Builder setRetentionPeriodDuration(Duration retentionPeriod) { abstract Builder clearLogging(); abstract Builder clearCustomPlacementConfig(); + + abstract Builder clearIpFilter(); } static final class BuilderImpl extends Builder { @@ -1958,6 +2393,7 @@ static final class BuilderImpl extends Builder { private SoftDeletePolicy softDeletePolicy; private HierarchicalNamespace hierarchicalNamespace; + private IpFilter ipFilter; private final ImmutableSet.Builder modifiedFields = ImmutableSet.builder(); BuilderImpl(String name) { @@ -1999,6 +2435,7 @@ static final class BuilderImpl extends Builder { objectRetention = bucketInfo.objectRetention; softDeletePolicy = bucketInfo.softDeletePolicy; hierarchicalNamespace = bucketInfo.hierarchicalNamespace; + ipFilter = bucketInfo.ipFilter; } @Override @@ -2404,6 +2841,15 @@ Builder setLocationType(String locationType) { return this; } + @Override + public Builder setIpFilter(IpFilter ipFilter) { + if (!Objects.equals(this.ipFilter, ipFilter)) { + modifiedFields.add(BucketField.IP_FILTER); + } + this.ipFilter = ipFilter; + return this; + } + @Override public BucketInfo build() { checkNotNull(name); @@ -2590,6 +3036,12 @@ BuilderImpl clearCustomPlacementConfig() { return this; } + @Override + BuilderImpl clearIpFilter() { + this.ipFilter = null; + return this; + } + private Builder clearDeleteLifecycleRules() { if (lifecycleRules != null && !lifecycleRules.isEmpty()) { ImmutableList nonDeleteRules = @@ -2638,6 +3090,7 @@ private Builder clearDeleteLifecycleRules() { objectRetention = builder.objectRetention; softDeletePolicy = builder.softDeletePolicy; hierarchicalNamespace = builder.hierarchicalNamespace; + ipFilter = builder.ipFilter; modifiedFields = builder.modifiedFields.build(); } @@ -2989,6 +3442,13 @@ public HierarchicalNamespace getHierarchicalNamespace() { return hierarchicalNamespace; } + /** + * @since 2.54.0 + */ + public @Nullable IpFilter getIpFilter() { + return ipFilter; + } + /** Returns a builder for the current bucket. */ public Builder toBuilder() { return new BuilderImpl(this); @@ -3030,7 +3490,8 @@ public int hashCode() { softDeletePolicy, customPlacementConfig, hierarchicalNamespace, - logging); + logging, + ipFilter); } @Override @@ -3075,7 +3536,8 @@ public boolean equals(Object o) { && Objects.equals(objectRetention, that.objectRetention) && Objects.equals(softDeletePolicy, that.softDeletePolicy) && Objects.equals(hierarchicalNamespace, that.hierarchicalNamespace) - && Objects.equals(logging, that.logging); + && Objects.equals(logging, that.logging) + && Objects.equals(ipFilter, that.ipFilter); } @Override diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcConversions.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcConversions.java index 4d9d5e31d..a530c3546 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcConversions.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcConversions.java @@ -16,6 +16,7 @@ package com.google.cloud.storage; +import static com.google.cloud.storage.Storage.BucketField.IP_FILTER; import static com.google.cloud.storage.Storage.BucketField.SOFT_DELETE_POLICY; import static com.google.cloud.storage.Utils.bucketNameCodec; import static com.google.cloud.storage.Utils.ifNonNull; @@ -30,6 +31,7 @@ import com.google.cloud.storage.Acl.Role; import com.google.cloud.storage.BlobInfo.CustomerEncryption; import com.google.cloud.storage.BucketInfo.CustomPlacementConfig; +import com.google.cloud.storage.BucketInfo.IpFilter; import com.google.cloud.storage.BucketInfo.LifecycleRule; import com.google.cloud.storage.BucketInfo.LifecycleRule.AbortIncompleteMPUAction; import com.google.cloud.storage.BucketInfo.Logging; @@ -44,6 +46,8 @@ import com.google.protobuf.Timestamp; import com.google.storage.v2.Bucket; import com.google.storage.v2.Bucket.Billing; +import com.google.storage.v2.Bucket.IpFilter.PublicNetworkSource; +import com.google.storage.v2.Bucket.IpFilter.VpcNetworkSource; import com.google.storage.v2.Bucket.Website; import com.google.storage.v2.BucketAccessControl; import com.google.storage.v2.CryptoKeyName; @@ -107,6 +111,14 @@ final class GrpcConversions { hierarchicalNamespaceCodec = Codec.of(this::hierarchicalNamespaceEncode, this::hierarchicalNamespaceDecode); + private final Codec ipFilterCodec = + Codec.of(this::ipFilterEncode, this::ipFilterDecode); + private final Codec + publicNetworkSourceCodec = + Codec.of(this::publicNetworkSourceEncode, this::publicNetworkSourceDecode); + private final Codec + vpcNetworkSourceCodec = Codec.of(this::vpcNetworkSourceEncode, this::vpcNetworkSourceDecode); + private final Codec byteStringB64StringCodec = Codec.of( bs -> Base64.getEncoder().encodeToString(bs.toByteArray()), @@ -296,7 +308,9 @@ private BucketInfo bucketInfoDecode(Bucket from) { to.setHierarchicalNamespace( hierarchicalNamespaceCodec.decode(from.getHierarchicalNamespace())); } - // TODO(frankyn): Add SelfLink when the field is available + if (from.hasIpFilter()) { + to.setIpFilter(ipFilterCodec.decode(from.getIpFilter())); + } if (!from.getEtag().isEmpty()) { to.setEtag(from.getEtag()); } @@ -390,7 +404,10 @@ private Bucket bucketInfoEncode(BucketInfo from) { from.getHierarchicalNamespace(), hierarchicalNamespaceCodec::encode, to::setHierarchicalNamespace); - // TODO(frankyn): Add SelfLink when the field is available + ifNonNull(from.getIpFilter(), ipFilterCodec::encode, to::setIpFilter); + if (from.getModifiedFields().contains(IP_FILTER) && from.getIpFilter() == null) { + to.clearIpFilter(); + } ifNonNull(from.getEtag(), to::setEtag); return to.build(); } @@ -1037,8 +1054,68 @@ private String removeKmsVersion(String from) { return from; } - private static T todo() { - throw new IllegalStateException("Not yet implemented"); + private Bucket.IpFilter ipFilterEncode(IpFilter from) { + Bucket.IpFilter.Builder to = Bucket.IpFilter.newBuilder(); + ifNonNull(from.getMode(), to::setMode); + ifNonNull( + from.getPublicNetworkSource(), + publicNetworkSourceCodec::encode, + to::setPublicNetworkSource); + ifNonNull( + from.getVpcNetworkSources(), + toImmutableListOf(vpcNetworkSourceCodec::encode), + to::addAllVpcNetworkSources); + ifNonNull(from.getAllowCrossOrgVpcs(), to::setAllowCrossOrgVpcs); + ifNonNull(from.getAllowAllServiceAgentAccess(), to::setAllowAllServiceAgentAccess); + return to.build(); + } + + private IpFilter ipFilterDecode(Bucket.IpFilter from) { + IpFilter.Builder to = IpFilter.newBuilder(); + if (!from.getMode().isEmpty()) { + to.setMode(from.getMode()); + } + ifNonNull( + from.getPublicNetworkSource(), + publicNetworkSourceCodec::decode, + to::setPublicNetworkSource); + ifNonNull( + from.getVpcNetworkSourcesList(), + toImmutableListOf(vpcNetworkSourceCodec::decode), + to::setVpcNetworkSources); + ifNonNull(from.getAllowCrossOrgVpcs(), to::setAllowCrossOrgVpcs); + if (from.hasAllowAllServiceAgentAccess()) { + to.setAllowAllServiceAgentAccess(from.getAllowAllServiceAgentAccess()); + } + return to.build(); + } + + private PublicNetworkSource publicNetworkSourceEncode(IpFilter.PublicNetworkSource from) { + PublicNetworkSource.Builder to = PublicNetworkSource.newBuilder(); + ifNonNull(from.getAllowedIpCidrRanges(), to::addAllAllowedIpCidrRanges); + return to.build(); + } + + private IpFilter.PublicNetworkSource publicNetworkSourceDecode(PublicNetworkSource from) { + return IpFilter.PublicNetworkSource.of(from.getAllowedIpCidrRangesList()); + } + + private VpcNetworkSource vpcNetworkSourceEncode(IpFilter.VpcNetworkSource from) { + VpcNetworkSource.Builder to = VpcNetworkSource.newBuilder(); + ifNonNull(from.getNetwork(), to::setNetwork); + ifNonNull(from.getAllowedIpCidrRanges(), to::addAllAllowedIpCidrRanges); + return to.build(); + } + + private IpFilter.VpcNetworkSource vpcNetworkSourceDecode(VpcNetworkSource from) { + IpFilter.VpcNetworkSource.Builder to = IpFilter.VpcNetworkSource.newBuilder(); + if (from.hasNetwork()) { + to.setNetwork(from.getNetwork()); + } + if (!from.getAllowedIpCidrRangesList().isEmpty()) { + to.setAllowedIpCidrRanges(from.getAllowedIpCidrRangesList()); + } + return to.build(); } /** diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/JsonConversions.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/JsonConversions.java index 7f9da1f58..c79fa288e 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/JsonConversions.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/JsonConversions.java @@ -16,6 +16,7 @@ package com.google.cloud.storage; +import static com.google.cloud.storage.Storage.BucketField.IP_FILTER; import static com.google.cloud.storage.Storage.BucketField.SOFT_DELETE_POLICY; import static com.google.cloud.storage.Utils.dateTimeCodec; import static com.google.cloud.storage.Utils.durationSecondsCodec; @@ -31,6 +32,7 @@ import com.google.api.services.storage.model.Bucket.Billing; import com.google.api.services.storage.model.Bucket.Encryption; import com.google.api.services.storage.model.Bucket.IamConfiguration.UniformBucketLevelAccess; +import com.google.api.services.storage.model.Bucket.IpFilter.VpcNetworkSources; import com.google.api.services.storage.model.Bucket.Lifecycle; import com.google.api.services.storage.model.Bucket.Lifecycle.Rule; import com.google.api.services.storage.model.Bucket.Lifecycle.Rule.Action; @@ -57,6 +59,7 @@ import com.google.cloud.storage.BucketInfo.Autoclass; import com.google.cloud.storage.BucketInfo.CustomPlacementConfig; import com.google.cloud.storage.BucketInfo.IamConfiguration; +import com.google.cloud.storage.BucketInfo.IpFilter; import com.google.cloud.storage.BucketInfo.LifecycleRule; import com.google.cloud.storage.BucketInfo.LifecycleRule.AbortIncompleteMPUAction; import com.google.cloud.storage.BucketInfo.LifecycleRule.DeleteLifecycleAction; @@ -149,6 +152,14 @@ final class JsonConversions { private final Codec iamConditionCodec = Codec.of(this::conditionEncode, this::conditionDecode); + private final Codec ipFilterCodec = + Codec.of(this::ipFilterEncode, this::ipFilterDecode); + private final Codec + publicNetworkSourceCodec = + Codec.of(this::publicNetworkSourceEncode, this::publicNetworkSourceDecode); + private final Codec + vpcNetworkSourceCodec = Codec.of(this::vpcNetworkSourceEncode, this::vpcNetworkSourceDecode); + private JsonConversions() {} Codec entity() { @@ -466,6 +477,10 @@ private Bucket bucketInfoEncode(BucketInfo from) { from.getHierarchicalNamespace(), this::hierarchicalNamespaceEncode, to::setHierarchicalNamespace); + ifNonNull(from.getIpFilter(), ipFilterCodec::encode, to::setIpFilter); + if (from.getModifiedFields().contains(IP_FILTER) && from.getIpFilter() == null) { + to.setIpFilter(Data.nullOf(Bucket.IpFilter.class)); + } return to; } @@ -519,6 +534,7 @@ private BucketInfo bucketInfoDecode(com.google.api.services.storage.model.Bucket to::setHierarchicalNamespace); ifNonNull(from.getObjectRetention(), this::objectRetentionDecode, to::setObjectRetention); ifNonNull(from.getSoftDeletePolicy(), this::softDeletePolicyDecode, to::setSoftDeletePolicy); + ifNonNull(from.getIpFilter(), ipFilterCodec::decode, to::setIpFilter); return to.build(); } @@ -1006,6 +1022,64 @@ private CustomPlacementConfig customPlacementConfigDecode(Bucket.CustomPlacement return CustomPlacementConfig.newBuilder().setDataLocations(from.getDataLocations()).build(); } + private Bucket.IpFilter ipFilterEncode(IpFilter from) { + Bucket.IpFilter to = new Bucket.IpFilter(); + ifNonNull(from.getMode(), to::setMode); + ifNonNull( + from.getPublicNetworkSource(), + publicNetworkSourceCodec::encode, + to::setPublicNetworkSource); + ifNonNull( + from.getVpcNetworkSources(), + toListOf(vpcNetworkSourceCodec::encode), + to::setVpcNetworkSources); + ifNonNull(from.getAllowCrossOrgVpcs(), to::setAllowCrossOrgVpcs); + ifNonNull(from.getAllowAllServiceAgentAccess(), to::setAllowAllServiceAgentAccess); + return to; + } + + private IpFilter ipFilterDecode(Bucket.IpFilter from) { + IpFilter.Builder to = IpFilter.newBuilder(); + ifNonNull(from.getMode(), to::setMode); + ifNonNull( + from.getPublicNetworkSource(), + publicNetworkSourceCodec::decode, + to::setPublicNetworkSource); + ifNonNull( + from.getVpcNetworkSources(), + toListOf(vpcNetworkSourceCodec::decode), + to::setVpcNetworkSources); + ifNonNull(from.getAllowCrossOrgVpcs(), to::setAllowCrossOrgVpcs); + ifNonNull(from.getAllowAllServiceAgentAccess(), to::setAllowAllServiceAgentAccess); + return to.build(); + } + + private Bucket.IpFilter.PublicNetworkSource publicNetworkSourceEncode( + IpFilter.PublicNetworkSource from) { + Bucket.IpFilter.PublicNetworkSource to = new Bucket.IpFilter.PublicNetworkSource(); + ifNonNull(from.getAllowedIpCidrRanges(), to::setAllowedIpCidrRanges); + return to; + } + + private IpFilter.PublicNetworkSource publicNetworkSourceDecode( + Bucket.IpFilter.PublicNetworkSource from) { + return IpFilter.PublicNetworkSource.of(from.getAllowedIpCidrRanges()); + } + + private Bucket.IpFilter.VpcNetworkSources vpcNetworkSourceEncode(IpFilter.VpcNetworkSource from) { + VpcNetworkSources to = new VpcNetworkSources(); + ifNonNull(from.getNetwork(), to::setNetwork); + ifNonNull(from.getAllowedIpCidrRanges(), to::setAllowedIpCidrRanges); + return to; + } + + private IpFilter.VpcNetworkSource vpcNetworkSourceDecode(Bucket.IpFilter.VpcNetworkSources from) { + IpFilter.VpcNetworkSource.Builder to = IpFilter.VpcNetworkSource.newBuilder(); + ifNonNull(from.getNetwork(), to::setNetwork); + ifNonNull(from.getAllowedIpCidrRanges(), to::setAllowedIpCidrRanges); + return to.build(); + } + private static void maybeEncodeRetentionPolicy(BucketInfo from, Bucket to) { if (from.getRetentionPeriodDuration() != null || from.retentionPolicyIsLocked() != null diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java index d2c38763e..61597307f 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java @@ -194,7 +194,13 @@ enum BucketField implements FieldSelector, NamedField { com.google.api.services.storage.model.Bucket.SoftDeletePolicy.class), @TransportCompatibility({Transport.HTTP, Transport.GRPC}) - PROJECT("projectNumber", "project", BigInteger.class); + PROJECT("projectNumber", "project", BigInteger.class), + /** + * @since 2.54.0 + */ + @TransportCompatibility({Transport.HTTP, Transport.GRPC}) + IP_FILTER("ipFilter", "ip_filter", com.google.api.services.storage.model.Bucket.IpFilter.class), + ; static final List REQUIRED_FIELDS = ImmutableList.of(NAME); private static final Map JSON_FIELD_NAME_INDEX; diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/UnifiedOpts.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/UnifiedOpts.java index 77cb1344a..29444ad13 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/UnifiedOpts.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/UnifiedOpts.java @@ -1084,6 +1084,7 @@ private Set getPaths() { BucketField.IAMCONFIGURATION.getGrpcName(), BucketInfo.Builder::clearIamConfiguration) .put(BucketField.ID.getGrpcName(), BucketInfo.Builder::clearGeneratedId) + .put(BucketField.IP_FILTER.getGrpcName(), BucketInfo.Builder::clearIpFilter) .put(BucketField.LABELS.getGrpcName(), BucketInfo.Builder::clearLabels) .put(BucketField.LIFECYCLE.getGrpcName(), BucketInfo.Builder::clearLifecycleRules) .put(BucketField.LOCATION.getGrpcName(), BucketInfo.Builder::clearLocation) diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBucketReadMaskTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBucketReadMaskTest.java index 36991f1b8..cb9b5515c 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBucketReadMaskTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBucketReadMaskTest.java @@ -115,6 +115,7 @@ public ImmutableList parameters() { new Args<>(BucketField.ETAG, LazyAssertion.equal()), new Args<>(BucketField.IAMCONFIGURATION, LazyAssertion.equal()), new Args<>(BucketField.ID, LazyAssertion.equal()), + new Args<>(BucketField.IP_FILTER, LazyAssertion.equal()), new Args<>(BucketField.LABELS, LazyAssertion.equal()), new Args<>(BucketField.LIFECYCLE, LazyAssertion.equal()), new Args<>(BucketField.LOCATION, LazyAssertion.equal()), diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITOptionRegressionTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITOptionRegressionTest.java index 905fe5478..e30fc3125 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITOptionRegressionTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITOptionRegressionTest.java @@ -61,6 +61,7 @@ import com.google.common.collect.ImmutableSet; import java.util.Locale; import java.util.Set; +import java.util.TreeSet; import java.util.function.Function; import org.junit.Before; import org.junit.Test; @@ -298,7 +299,7 @@ public void storage_BucketGetOption_userProject_String() { @Test public void storage_BucketGetOption_fields_BucketField() { Set expected = - ImmutableSet.of( + treeSet( "acl", "autoclass", "billing", @@ -310,6 +311,7 @@ public void storage_BucketGetOption_fields_BucketField() { "etag", "iamConfiguration", "id", + "ipFilter", "labels", "lifecycle", "location", @@ -705,7 +707,7 @@ public void storage_BlobGetOption_metagenerationNotMatch_long() { @Test public void storage_BlobGetOption_fields_BlobField() { Set expected = - ImmutableSet.of( + treeSet( "acl", "bucket", "cacheControl", @@ -790,7 +792,7 @@ public void storage_BucketListOption_userProject_String() { @Test public void storage_BucketListOption_fields_BucketField() { Set expected = - ImmutableSet.of( + treeSet( "nextPageToken", "items/acl", "items/autoclass", @@ -803,6 +805,7 @@ public void storage_BucketListOption_fields_BucketField() { "items/etag", "items/iamConfiguration", "items/id", + "items/ipFilter", "items/labels", "items/lifecycle", "items/location", @@ -883,7 +886,7 @@ public void storage_BlobListOption_versions_boolean() { @Test public void storage_BlobListOption_fields_BlobField() { Set expected = - ImmutableSet.of( + treeSet( "nextPageToken", "prefixes", "items/acl", @@ -1194,6 +1197,15 @@ private static String objectName() { } private static Function> splitOnCommaToSet() { - return s -> ImmutableSet.copyOf(s.split(",")); + return s -> treeSet(s.split(",")); + } + + /** + * Util method to make a TreeSet easily. This makes failed assertions easier to read by sorting + * the values. + */ + @SafeVarargs + private static > Set treeSet(T... ts) { + return new TreeSet<>(ImmutableSet.copyOf(ts)); } } diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/jqwik/BucketArbitraryProvider.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/jqwik/BucketArbitraryProvider.java index 1839c32b4..9b71a59ac 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/jqwik/BucketArbitraryProvider.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/jqwik/BucketArbitraryProvider.java @@ -77,9 +77,7 @@ public Set> provideFor(TypeUsage targetType, SubtypeProvider subtyp .as(Tuple::of), Combinators.combine( StorageArbitraries.projectNumber().map(ProjectNumber::toProjectName), - StorageArbitraries - .alnum() // ignored for now, tuples can't be a single element - ) + StorageArbitraries.buckets().ipFilter().injectNull(0.75)) .as(Tuple::of)) .as( (t1, t2, t3, t4) -> { @@ -109,6 +107,7 @@ public Set> provideFor(TypeUsage targetType, SubtypeProvider subtyp ifNonNull(t3.get7(), b::putAllLabels); ifNonNull(t3.get8(), b::setEtag); ifNonNull(t4.get1(), ProjectName::toString, b::setProject); + ifNonNull(t4.get2(), b::setIpFilter); // TODO: add CustomPlacementConfig return b.build(); }); diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/jqwik/StorageArbitraries.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/jqwik/StorageArbitraries.java index f5ee93ce0..0b6e21d98 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/jqwik/StorageArbitraries.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/jqwik/StorageArbitraries.java @@ -26,6 +26,9 @@ import com.google.storage.v2.Bucket; import com.google.storage.v2.Bucket.Billing; import com.google.storage.v2.Bucket.Encryption; +import com.google.storage.v2.Bucket.IpFilter; +import com.google.storage.v2.Bucket.IpFilter.PublicNetworkSource; +import com.google.storage.v2.Bucket.IpFilter.VpcNetworkSource; import com.google.storage.v2.Bucket.Lifecycle.Rule.Condition; import com.google.storage.v2.Bucket.Logging; import com.google.storage.v2.Bucket.RetentionPolicy; @@ -58,6 +61,7 @@ import net.jqwik.api.providers.TypeUsage; import net.jqwik.time.api.DateTimes; import net.jqwik.web.api.Web; +import org.checkerframework.checker.nullness.qual.Nullable; public final class StorageArbitraries { @@ -172,6 +176,19 @@ public static Arbitrary etag() { .edgeCases(config -> config.add("")); } + /** Arbitrary of ipv4 and ipv6 cidr ranges */ + public static Arbitrary cidr() { + return Arbitraries.oneOf(cidrIpv4(), cidrIpv6()); + } + + public static Arbitrary cidrIpv4() { + return Arbitraries.of("182.0.2.0/24"); + } + + public static Arbitrary cidrIpv6() { + return Arbitraries.of("2001:db8::/32"); + } + public static final class Buckets { private static final Buckets INSTANCE = new Buckets(); @@ -429,6 +446,66 @@ public Arbitrary locationType() { public Arbitrary> labels() { return objects().customMetadata(); } + + public Arbitrary ipFilter() { + return Combinators.combine( + Arbitraries.of("Enabled", "Disabled").injectNull(0.33), // mode + publicNetworkSource(), + vpcNetworkSource().list().ofMinSize(1).ofMaxSize(3).injectNull(0.5), + bool().injectNull(0.5), // allow_cross_org_vpcs + bool().injectNull(0.5) // allow_all_service_agent_access + ) + .as( + (mode, pns, vnss, allowCrossOrgVpcs, allowAllServiceAgentAccess) -> { + IpFilter.Builder b = IpFilter.newBuilder(); + ifNonNull(mode, b::setMode); + ifNonNull(pns, b::setPublicNetworkSource); + ifNonNull(vnss, b::addAllVpcNetworkSources); + ifNonNull(allowCrossOrgVpcs, b::setAllowCrossOrgVpcs); + ifNonNull(allowAllServiceAgentAccess, b::setAllowAllServiceAgentAccess); + return b.build(); + }); + } + + public Arbitrary publicNetworkSource() { + return Arbitraries.oneOf(cidr().list().ofMinSize(1).ofMaxSize(3).injectNull(0.5)) + .map( + ranges -> { + PublicNetworkSource.Builder b = PublicNetworkSource.newBuilder(); + ifNonNull(ranges, b::addAllAllowedIpCidrRanges); + return b.build(); + }); + } + + public Arbitrary vpcNetworkSource() { + return Combinators.combine( + networkResource().injectNull(0.25), + cidr().list().ofMinSize(1).ofMaxSize(3).injectNull(0.5)) + .as( + (network, ranges) -> { + VpcNetworkSource.Builder b = VpcNetworkSource.newBuilder(); + ifNonNull(network, b::setNetwork); + ifNonNull(ranges, b::addAllAllowedIpCidrRanges); + return b.build(); + }); + } + + Arbitrary networkResource() { + return Combinators.combine(projectID(), networkName()) + .as( + (projectId, networkName) -> + String.format( + Locale.US, "projects/%s/global/networks/%s", projectId, networkName)); + } + + Arbitrary<@Nullable String> networkName() { + return Arbitraries.strings() + .withCharRange('a', 'z') + .numeric() + .withChars('-') + .ofMinLength(1) + .ofMaxLength(10); + } } public static final class ProjectID { From fa0f6a03380af78e239bd0079267649ba4138f38 Mon Sep 17 00:00:00 2001 From: BenWhitehead Date: Wed, 23 Jul 2025 12:20:34 -0400 Subject: [PATCH 11/15] chore: merge train for e2e-crc32c-media related upload PRs (#3197) Merge train for * chore: cleanup Crc32cValue and associated Hasher operations #3167 * chore: add Hasher#defaultHasher() #3173 * chore: add UnifiedOpts.Opts#getHasher() to return a hasher relative to the set of Opts defined for an operation. #3174 * feat: add default end-to-end crc32c checksumming for several upload methods via grpc transport #3176 * feat: add default end-to-end checksumming for JournalingBlobWriteSessionConfig #3180 * fix: give user provided checksum precondition priority for Storage#create methods that accept byte[] #3182 * fix: move crc32c computation before writing to disk for BufferToDiskThenUpload BlobWriteSession config #3187 --- .../cloud/storage/BufferToDiskThenUpload.java | 75 ++++-- .../com/google/cloud/storage/Crc32cValue.java | 14 ++ .../DefaultBlobWriteSessionConfig.java | 2 +- ...apicWritableByteChannelSessionBuilder.java | 38 +++- .../google/cloud/storage/GrpcStorageImpl.java | 10 +- .../java/com/google/cloud/storage/Hasher.java | 66 +++++- .../JournalingBlobWriteSessionConfig.java | 5 +- .../com/google/cloud/storage/StorageImpl.java | 82 ++----- .../com/google/cloud/storage/UnifiedOpts.java | 97 +++++--- .../com/google/cloud/storage/WriteCtx.java | 14 +- .../storage/BufferToDiskThenUploadTest.java | 98 ++++++++ .../google/cloud/storage/Crc32cValueTest.java | 28 +++ ...unkedResumableWritableByteChannelTest.java | 54 ++--- ...bufferedDirectWritableByteChannelTest.java | 29 ++- ...CloseResumableWritableByteChannelTest.java | 20 +- ...apicUnbufferedWritableByteChannelTest.java | 8 +- ...fferedWritableByteChannelPropertyTest.java | 59 +++-- ...ompositeUploadWritableByteChannelTest.java | 3 +- .../cloud/storage/StorageImplMockitoTest.java | 213 +----------------- .../com/google/cloud/storage/TestUtils.java | 23 ++ .../java/com/google/cloud/storage/TmpDir.java | 59 +++++ .../google/cloud/storage/UnifiedOptsTest.java | 29 ++- .../storage/it/ChecksummedTestContent.java | 14 +- ...ITBlobWriteSessionCommonSemanticsTest.java | 47 ++++ .../it/ITObjectChecksumSupportTest.java | 72 ++++++ 25 files changed, 722 insertions(+), 437 deletions(-) create mode 100644 google-cloud-storage/src/test/java/com/google/cloud/storage/TmpDir.java diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/BufferToDiskThenUpload.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/BufferToDiskThenUpload.java index bfd85c1d8..d831f2737 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/BufferToDiskThenUpload.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/BufferToDiskThenUpload.java @@ -28,6 +28,8 @@ import com.google.cloud.storage.UnifiedOpts.Opts; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; +import com.google.common.hash.Hasher; +import com.google.common.hash.Hashing; import com.google.common.util.concurrent.MoreExecutors; import java.io.IOException; import java.io.ObjectInputStream; @@ -42,6 +44,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Objects; +import java.util.concurrent.locks.ReentrantLock; import java.util.stream.Collector; import javax.annotation.concurrent.Immutable; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @@ -63,6 +66,7 @@ @TransportCompatibility({Transport.GRPC, Transport.HTTP}) public final class BufferToDiskThenUpload extends BlobWriteSessionConfig implements BlobWriteSessionConfig.HttpCompatible, BlobWriteSessionConfig.GrpcCompatible { + private static final long serialVersionUID = 9059242302276891867L; /** @@ -211,41 +215,78 @@ public ApiFuture getResult() { return result; } + @SuppressWarnings("UnstableApiUsage") private final class Flusher implements WritableByteChannel { private final WritableByteChannel delegate; + private final Hasher cumulativeCrc32c; + private final ReentrantLock lock; private Flusher(WritableByteChannel delegate) { this.delegate = delegate; + this.cumulativeCrc32c = + opts.getHasher().initialValue() == null ? null : Hashing.crc32c().newHasher(); + this.lock = new ReentrantLock(); } @Override public int write(ByteBuffer src) throws IOException { - return delegate.write(src); + lock.lock(); + try { + if (cumulativeCrc32c != null) { + cumulativeCrc32c.putBytes(src.duplicate()); + } + return delegate.write(src); + } finally { + lock.unlock(); + } } @Override public boolean isOpen() { - return delegate.isOpen(); + lock.lock(); + try { + return delegate.isOpen(); + } finally { + lock.unlock(); + } } @Override public void close() throws IOException { - delegate.close(); - try (RecoveryFile rf = Factory.WriteToFileThenUpload.this.rf) { - Path path = rf.getPath(); - long size = Files.size(path); - ThroughputSink.computeThroughput( - clock, - gcs, - size, - () -> { - BlobInfo blob = storage.internalCreateFrom(path, info, opts); - result.set(blob); - }); - } catch (StorageException | IOException e) { - result.setException(e); - throw e; + lock.lock(); + try { + + delegate.close(); + try (RecoveryFile rf = Factory.WriteToFileThenUpload.this.rf) { + Path path = rf.getPath(); + long size = Files.size(path); + ThroughputSink.computeThroughput( + clock, + gcs, + size, + () -> { + BlobInfo pendingInfo = info; + Opts pendingOpts = opts; + if (cumulativeCrc32c != null) { + int hashCodeInt = cumulativeCrc32c.hash().asInt(); + pendingInfo = + pendingInfo.toBuilder() + .clearMd5() + .clearCrc32c() + .setCrc32c(Utils.crc32cCodec.encode(hashCodeInt)) + .build(); + pendingOpts = opts.prepend(Opts.from(UnifiedOpts.crc32cMatch(hashCodeInt))); + } + BlobInfo blob = storage.internalCreateFrom(path, pendingInfo, pendingOpts); + result.set(blob); + }); + } catch (StorageException | IOException e) { + result.setException(e); + throw e; + } + } finally { + lock.unlock(); } } } diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Crc32cValue.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Crc32cValue.java index 245999dd7..5da5a2037 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Crc32cValue.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Crc32cValue.java @@ -16,6 +16,7 @@ package com.google.cloud.storage; +import java.nio.ByteBuffer; import java.util.Locale; import java.util.Objects; @@ -56,6 +57,10 @@ public boolean eqValue(Crc32cValue other) { return this.getValue() == other.getValue(); } + static Crc32cLengthKnown zero() { + return Crc32cLengthKnown.ZERO; + } + static Crc32cLengthUnknown of(int value) { return new Crc32cLengthUnknown(value); } @@ -81,6 +86,9 @@ public int getValue() { @Override public Crc32cLengthUnknown concat(Crc32cLengthKnown other) { + if (other == Crc32cLengthKnown.ZERO) { + return this; + } int combined = Crc32cUtility.concatCrc32c(value, other.value, other.length); return new Crc32cLengthUnknown(combined); } @@ -118,6 +126,7 @@ public int hashCode() { } static final class Crc32cLengthKnown extends Crc32cValue { + private static final Crc32cLengthKnown ZERO = Hasher.enabled().hash(ByteBuffer.allocate(0)); private final int value; private final long length; @@ -137,6 +146,11 @@ public long getLength() { @Override public Crc32cLengthKnown concat(Crc32cLengthKnown other) { + if (other == ZERO) { + return this; + } else if (this == ZERO) { + return other; + } int combined = Crc32cUtility.concatCrc32c(value, other.value, other.length); return new Crc32cLengthKnown(combined, length + other.length); } diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/DefaultBlobWriteSessionConfig.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/DefaultBlobWriteSessionConfig.java index 67360ad17..53a14ca26 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/DefaultBlobWriteSessionConfig.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/DefaultBlobWriteSessionConfig.java @@ -160,7 +160,7 @@ public WritableByteChannelSession writeSession( grpc.storageClient .writeObjectCallable() .withDefaultCallContext(grpcCallContext)) - .setHasher(Hasher.noop()) + .setHasher(opts.getHasher()) .setByteStringStrategy(ByteStringStrategy.copy()) .resumable() .withRetryConfig( diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/GapicWritableByteChannelSessionBuilder.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/GapicWritableByteChannelSessionBuilder.java index ff73dc689..a256d39b7 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/GapicWritableByteChannelSessionBuilder.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/GapicWritableByteChannelSessionBuilder.java @@ -50,14 +50,14 @@ final class GapicWritableByteChannelSessionBuilder { GapicWritableByteChannelSessionBuilder( ClientStreamingCallable write) { this.write = write; - this.hasher = Hasher.noop(); + this.hasher = Hasher.defaultHasher(); this.byteStringStrategy = ByteStringStrategy.copy(); } /** * Set the {@link Hasher} to apply to the bytes passing through the built session's channel. * - *

Default: {@link Hasher#noop()} + *

Default: {@link Hasher#defaultHasher()} * * @see Hasher#enabled() * @see Hasher#noop() @@ -179,14 +179,17 @@ UnbufferedDirectUploadBuilder setRequest(WriteObjectRequest req) { } UnbufferedWritableByteChannelSession build() { + ChunkSegmenter chunkSegmenter = getChunkSegmenter(); return new UnbufferedWriteSession<>( ApiFutures.immediateFuture(requireNonNull(req, "req must be non null")), lift((WriteObjectRequest start, SettableApiFuture resultFuture) -> new GapicUnbufferedDirectWritableByteChannel( resultFuture, - getChunkSegmenter(), + chunkSegmenter, write, - new WriteCtx<>(WriteObjectRequestBuilderFactory.simple(start)))) + WriteCtx.of( + WriteObjectRequestBuilderFactory.simple(start), + chunkSegmenter.getHasher()))) .andThen(StorageByteChannels.writable()::createSynchronized)); } } @@ -207,14 +210,17 @@ BufferedDirectUploadBuilder setRequest(WriteObjectRequest req) { } BufferedWritableByteChannelSession build() { + ChunkSegmenter chunkSegmenter = getChunkSegmenter(); return new BufferedWriteSession<>( ApiFutures.immediateFuture(requireNonNull(req, "req must be non null")), lift((WriteObjectRequest start, SettableApiFuture resultFuture) -> new GapicUnbufferedDirectWritableByteChannel( resultFuture, - getChunkSegmenter(), + chunkSegmenter, write, - new WriteCtx<>(WriteObjectRequestBuilderFactory.simple(start)))) + WriteCtx.of( + WriteObjectRequestBuilderFactory.simple(start), + chunkSegmenter.getHasher()))) .andThen(c -> new DefaultBufferedWritableByteChannel(bufferHandle, c)) .andThen(StorageByteChannels.writable()::createSynchronized)); } @@ -290,20 +296,24 @@ UnbufferedResumableUploadBuilder setStartAsync(ApiFuture start) UnbufferedWritableByteChannelSession build() { RetrierWithAlg boundRetrier = retrier; + ChunkSegmenter chunkSegmenter = getChunkSegmenter(); return new UnbufferedWriteSession<>( requireNonNull(start, "start must be non null"), lift((ResumableWrite start, SettableApiFuture result) -> { if (fsyncEvery) { return new GapicUnbufferedChunkedResumableWritableByteChannel( result, - getChunkSegmenter(), + chunkSegmenter, write, - new WriteCtx<>(start), + WriteCtx.of(start, chunkSegmenter.getHasher()), boundRetrier, Retrying::newCallContext); } else { return new GapicUnbufferedFinalizeOnCloseResumableWritableByteChannel( - result, getChunkSegmenter(), write, new WriteCtx<>(start)); + result, + chunkSegmenter, + write, + WriteCtx.of(start, chunkSegmenter.getHasher())); } }) .andThen(StorageByteChannels.writable()::createSynchronized)); @@ -330,20 +340,24 @@ BufferedResumableUploadBuilder setStartAsync(ApiFuture start) { } BufferedWritableByteChannelSession build() { + ChunkSegmenter chunkSegmenter = getChunkSegmenter(); return new BufferedWriteSession<>( requireNonNull(start, "start must be non null"), lift((ResumableWrite start, SettableApiFuture result) -> { if (fsyncEvery) { return new GapicUnbufferedChunkedResumableWritableByteChannel( result, - getChunkSegmenter(), + chunkSegmenter, write, - new WriteCtx<>(start), + WriteCtx.of(start, chunkSegmenter.getHasher()), retrier, Retrying::newCallContext); } else { return new GapicUnbufferedFinalizeOnCloseResumableWritableByteChannel( - result, getChunkSegmenter(), write, new WriteCtx<>(start)); + result, + chunkSegmenter, + write, + WriteCtx.of(start, chunkSegmenter.getHasher())); } }) .andThen(c -> new DefaultBufferedWritableByteChannel(bufferHandle, c)) diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcStorageImpl.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcStorageImpl.java index 50b3596c9..7d1192464 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcStorageImpl.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcStorageImpl.java @@ -263,7 +263,7 @@ public Blob create(BlobInfo blobInfo, InputStream content, BlobWriteOption... op GrpcCallContext grpcCallContext = optsWithDefaults.grpcMetadataMapper().apply(GrpcCallContext.createDefault()); WriteObjectRequest req = getWriteObjectRequest(blobInfo, optsWithDefaults); - Hasher hasher = Hasher.enabled(); + Hasher hasher = optsWithDefaults.getHasher(); GrpcCallContext merge = Utils.merge(grpcCallContext, Retrying.newCallContext()); UnbufferedWritableByteChannelSession session = ResumableMedia.gapic() @@ -324,7 +324,7 @@ public Blob internalCreateFrom(Path path, BlobInfo info, Opts o write, storageClient.queryWriteStatusCallable(), rw, - Hasher.noop()), + opts.getHasher()), MoreExecutors.directExecutor()); try { GrpcResumableSession got = session2.get(); @@ -365,7 +365,7 @@ public Blob createFrom( .write() .byteChannel( storageClient.writeObjectCallable().withDefaultCallContext(grpcCallContext)) - .setHasher(Hasher.noop()) + .setHasher(opts.getHasher()) .setByteStringStrategy(ByteStringStrategy.noCopy()) .resumable() .withRetryConfig(retrier.withAlg(retryAlgorithmManager.idempotent())) @@ -779,7 +779,7 @@ public GrpcBlobWriteChannel writer(BlobInfo blobInfo, BlobWriteOption... options GrpcCallContext grpcCallContext = opts.grpcMetadataMapper().apply(GrpcCallContext.createDefault()); WriteObjectRequest req = getWriteObjectRequest(blobInfo, opts); - Hasher hasher = Hasher.noop(); + Hasher hasher = opts.getHasher(); // in JSON, the starting of the resumable session happens before the invocation of write can // happen. Emulate the same thing here. // 1. create the future @@ -804,7 +804,7 @@ public BlobInfo internalDirectUpload( GrpcCallContext grpcCallContext = optsWithDefaults.grpcMetadataMapper().apply(GrpcCallContext.createDefault()); WriteObjectRequest req = getWriteObjectRequest(blobInfo, optsWithDefaults); - Hasher hasher = Hasher.enabled(); + Hasher hasher = opts.getHasher(); GrpcCallContext merge = Utils.merge(grpcCallContext, Retrying.newCallContext()); RewindableContent content = RewindableContent.of(buf); return retrier.run( diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Hasher.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Hasher.java index 3342fd8c3..47a7b029e 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Hasher.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Hasher.java @@ -27,11 +27,35 @@ import java.util.List; import java.util.Locale; import java.util.function.Supplier; +import java.util.logging.Logger; +import javax.annotation.ParametersAreNonnullByDefault; import javax.annotation.concurrent.Immutable; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; +@SuppressWarnings("ClassEscapesDefinedScope") +@ParametersAreNonnullByDefault interface Hasher { + final class DefaultInstanceHolder { + private static final Logger LOGGER = Logger.getLogger(Hasher.class.getName()); + private static final String PROPERTY_NAME = "com.google.cloud.storage.Hasher.default"; + private static final String PROPERTY_VALUE = System.getProperty(PROPERTY_NAME, "enabled"); + static final Hasher DEFAULT_HASHER; + + static { + LOGGER.fine(String.format(Locale.US, "-D%s=%s", PROPERTY_NAME, PROPERTY_VALUE)); + if ("disabled".equalsIgnoreCase(PROPERTY_VALUE)) { + DEFAULT_HASHER = noop(); + } else { + try { + Class.forName("java.util.zip.CRC32C"); + } catch (ClassNotFoundException e) { + LOGGER.fine("Fast CRC32C implementation (Java 9+) is not available."); + } + DEFAULT_HASHER = enabled(); + } + } + } @Nullable default Crc32cLengthKnown hash(Supplier b) { @@ -49,16 +73,30 @@ default Crc32cLengthKnown hash(Supplier b) { void validateUnchecked(Crc32cValue expected, ByteString byteString) throws UncheckedChecksumMismatchException; - @Nullable Crc32cLengthKnown nullSafeConcat(Crc32cLengthKnown r1, Crc32cLengthKnown r2); + @Nullable Crc32cLengthKnown nullSafeConcat( + @Nullable Crc32cLengthKnown r1, @NonNull Crc32cLengthKnown r2); - static Hasher noop() { + /** + * The initial value to use for this hasher. + * + *

Not ideal, really we should always start with {@link Crc32cValue#zero()} but this saves us + * from having to plumb the initial value along with the actual hasher to the constructor of the + * WriteCtx when hashing is disabled because of user provided crc32c/md5 preconditions. + */ + @Nullable Crc32cLengthKnown initialValue(); + + static NoOpHasher noop() { return NoOpHasher.INSTANCE; } - static Hasher enabled() { + static GuavaHasher enabled() { return GuavaHasher.INSTANCE; } + static Hasher defaultHasher() { + return DefaultInstanceHolder.DEFAULT_HASHER; + } + @Immutable class NoOpHasher implements Hasher { private static final NoOpHasher INSTANCE = new NoOpHasher(); @@ -85,7 +123,13 @@ public void validate(Crc32cValue expected, ByteString b) {} public void validateUnchecked(Crc32cValue expected, ByteString byteString) {} @Override - public @Nullable Crc32cLengthKnown nullSafeConcat(Crc32cLengthKnown r1, Crc32cLengthKnown r2) { + public @Nullable Crc32cLengthKnown nullSafeConcat( + @Nullable Crc32cLengthKnown r1, @NonNull Crc32cLengthKnown r2) { + return null; + } + + @Override + public @Nullable Crc32cLengthKnown initialValue() { return null; } } @@ -107,7 +151,7 @@ private GuavaHasher() {} return Crc32cValue.of(Hashing.crc32c().hashBytes(b).asInt(), remaining); } - @SuppressWarnings({"ConstantConditions", "UnstableApiUsage"}) + @SuppressWarnings({"UnstableApiUsage"}) @Override public @NonNull Crc32cLengthKnown hash(ByteString byteString) { List buffers = byteString.asReadOnlyByteBufferList(); @@ -118,7 +162,6 @@ private GuavaHasher() {} return Crc32cValue.of(crc32c.hash().asInt(), byteString.size()); } - @SuppressWarnings({"ConstantConditions"}) @Override public void validate(Crc32cValue expected, ByteString byteString) throws ChecksumMismatchException { @@ -137,7 +180,6 @@ public void validate(Crc32cValue expected, Supplier b) } } - @SuppressWarnings({"ConstantConditions"}) @Override public void validateUnchecked(Crc32cValue expected, ByteString byteString) throws UncheckedChecksumMismatchException { @@ -149,13 +191,19 @@ public void validateUnchecked(Crc32cValue expected, ByteString byteString) @Override @Nullable - public Crc32cLengthKnown nullSafeConcat(Crc32cLengthKnown r1, Crc32cLengthKnown r2) { + public Crc32cLengthKnown nullSafeConcat( + @Nullable Crc32cLengthKnown r1, @NonNull Crc32cLengthKnown r2) { if (r1 == null) { - return r2; + return null; } else { return r1.concat(r2); } } + + @Override + public @NonNull Crc32cLengthKnown initialValue() { + return Crc32cValue.zero(); + } } final class ChecksumMismatchException extends IOException { diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/JournalingBlobWriteSessionConfig.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/JournalingBlobWriteSessionConfig.java index b770a1b4e..d8db80a65 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/JournalingBlobWriteSessionConfig.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/JournalingBlobWriteSessionConfig.java @@ -192,7 +192,8 @@ public WritableByteChannelSession writeSession( grpcStorage.startResumableWrite( grpcCallContext, grpcStorage.getWriteObjectRequest(info, opts), opts); ApiFuture> start = - ApiFutures.transform(f, WriteCtx::new, MoreExecutors.directExecutor()); + ApiFutures.transform( + f, s -> WriteCtx.of(s, opts.getHasher()), MoreExecutors.directExecutor()); ClientStreamingCallable write = grpcStorage.storageClient.writeObjectCallable().withDefaultCallContext(grpcCallContext); @@ -200,7 +201,7 @@ public WritableByteChannelSession writeSession( ResumableMedia.gapic() .write() .byteChannel(write) - .setHasher(Hasher.noop()) + .setHasher(opts.getHasher()) .setByteStringStrategy(ByteStringStrategy.copy()) .journaling() .withRetryConfig( diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java index bfa956011..1974183ac 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java @@ -41,6 +41,7 @@ import com.google.cloud.storage.BlobReadChannelV2.BlobReadChannelContext; import com.google.cloud.storage.BlobWriteSessionConfig.WriterFactory; import com.google.cloud.storage.Conversions.Decoder; +import com.google.cloud.storage.Crc32cValue.Crc32cLengthKnown; import com.google.cloud.storage.HmacKey.HmacKeyMetadata; import com.google.cloud.storage.PostPolicyV4.ConditionV4Type; import com.google.cloud.storage.PostPolicyV4.PostConditionsV4; @@ -55,7 +56,6 @@ import com.google.cloud.storage.spi.v1.StorageRpc; import com.google.cloud.storage.spi.v1.StorageRpc.RewriteRequest; import com.google.common.base.CharMatcher; -import com.google.common.base.Preconditions; import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; @@ -63,10 +63,8 @@ import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Maps; -import com.google.common.hash.Hashing; import com.google.common.io.BaseEncoding; import com.google.common.io.CountingOutputStream; -import com.google.common.primitives.Ints; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; @@ -97,7 +95,6 @@ import java.util.concurrent.TimeoutException; import java.util.function.Supplier; import java.util.stream.Stream; -import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; final class StorageImpl extends BaseService implements Storage, StorageInternal { @@ -152,46 +149,23 @@ public Bucket create(BucketInfo bucketInfo, BucketTargetOption... options) { @Override public Blob create(BlobInfo blobInfo, BlobTargetOption... options) { - BlobInfo updatedInfo = - blobInfo.toBuilder() - .setMd5(EMPTY_BYTE_ARRAY_MD5) - .setCrc32c(EMPTY_BYTE_ARRAY_CRC32C) - .build(); - final Opts objectTargetOptOpts = Opts.unwrap(options).resolveFrom(updatedInfo); - return internalCreate(updatedInfo, EMPTY_BYTE_ARRAY, 0, 0, objectTargetOptOpts); + Opts opts = Opts.unwrap(options).resolveFrom(blobInfo); + return internalDirectUpload(blobInfo, opts, Buffers.allocate(0)).asBlob(this); } @Override public Blob create(BlobInfo blobInfo, byte[] content, BlobTargetOption... options) { content = firstNonNull(content, EMPTY_BYTE_ARRAY); - BlobInfo updatedInfo = - blobInfo.toBuilder() - .setMd5(BaseEncoding.base64().encode(Hashing.md5().hashBytes(content).asBytes())) - .setCrc32c( - BaseEncoding.base64() - .encode(Ints.toByteArray(Hashing.crc32c().hashBytes(content).asInt()))) - .build(); - final Opts objectTargetOptOpts = Opts.unwrap(options).resolveFrom(updatedInfo); - return internalCreate(updatedInfo, content, 0, content.length, objectTargetOptOpts); + Opts opts = Opts.unwrap(options).resolveFrom(blobInfo); + return internalDirectUpload(blobInfo, opts, ByteBuffer.wrap(content)).asBlob(this); } @Override public Blob create( BlobInfo blobInfo, byte[] content, int offset, int length, BlobTargetOption... options) { - content = firstNonNull(content, EMPTY_BYTE_ARRAY); - BlobInfo updatedInfo = - blobInfo.toBuilder() - .setMd5( - BaseEncoding.base64() - .encode(Hashing.md5().hashBytes(content, offset, length).asBytes())) - .setCrc32c( - BaseEncoding.base64() - .encode( - Ints.toByteArray( - Hashing.crc32c().hashBytes(content, offset, length).asInt()))) - .build(); - final Opts objectTargetOptOpts = Opts.unwrap(options).resolveFrom(updatedInfo); - return internalCreate(updatedInfo, content, offset, length, objectTargetOptOpts); + Opts opts = Opts.unwrap(options).resolveFrom(blobInfo); + return internalDirectUpload(blobInfo, opts, ByteBuffer.wrap(content, offset, length)) + .asBlob(this); } @Override @@ -212,30 +186,6 @@ public Blob create(BlobInfo blobInfo, InputStream content, BlobWriteOption... op return info.asBlob(this); } - private Blob internalCreate( - BlobInfo info, - final byte @NonNull [] content, - final int offset, - final int length, - Opts opts) { - Preconditions.checkNotNull(content); - final Map optionsMap = opts.getRpcOptions(); - - BlobInfo updated = opts.blobInfoMapper().apply(info.toBuilder()).build(); - final StorageObject blobPb = codecs.blobInfo().encode(updated); - ResultRetryAlgorithm algorithm = - retryAlgorithmManager.getForObjectsCreate(blobPb, optionsMap); - return run( - algorithm, - () -> - storageRpc.create( - blobPb, new ByteArrayInputStream(content, offset, length), optionsMap), - (x) -> { - BlobInfo info1 = Conversions.json().blobInfo().decode(x); - return info1.asBlob(this); - }); - } - @Override public Blob createFrom(BlobInfo blobInfo, Path path, BlobWriteOption... options) throws IOException { @@ -1731,7 +1681,7 @@ public BlobInfo internalCreateFrom(Path path, BlobInfo info, Opts optionsMap = opts.getRpcOptions(); BlobInfo.Builder builder = info.toBuilder().setMd5(null).setCrc32c(null); @@ -1767,17 +1717,15 @@ public BlobInfo internalCreateFrom(Path path, BlobInfo info, Opts opts, ByteBuffer buf) { - BlobInfo.Builder builder = - info.toBuilder() - .setMd5( - BaseEncoding.base64().encode(Hashing.md5().hashBytes(buf.duplicate()).asBytes())) - .setCrc32c( - BaseEncoding.base64() - .encode(Ints.toByteArray(Hashing.crc32c().hashBytes(buf.duplicate()).asInt()))); + opts.blobInfoMapper().apply(info.toBuilder().clearMd5().clearCrc32c()); + @Nullable Crc32cLengthKnown hash = opts.getHasher().hash(buf.duplicate()); + if (hash != null) { + builder.setCrc32c(Utils.crc32cCodec.encode(hash.getValue())); + } final Map optionsMap = opts.getRpcOptions(); - BlobInfo updated = opts.blobInfoMapper().apply(builder).build(); + BlobInfo updated = builder.build(); final StorageObject encoded = codecs.blobInfo().encode(updated); ResultRetryAlgorithm algorithm = retryAlgorithmManager.getForObjectsCreate(encoded, optionsMap); diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/UnifiedOpts.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/UnifiedOpts.java index 29444ad13..3444323cf 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/UnifiedOpts.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/UnifiedOpts.java @@ -281,6 +281,10 @@ interface ProjectAsSource { O asSource(); } + interface HasherSelector extends BucketObjectHmacKeyAllOpt { + Hasher getHasher(); + } + /** * This class extends off {@link ObjectSourceOpt} and {@link ObjectTargetOpt} in order to satisfy * some the shimming constraints of the subclasses of {@link OptionShim}. @@ -589,7 +593,11 @@ static Headers extraHeaders(ImmutableMap extraHeaders) { return new Headers(extraHeaders); } - static final class Crc32cMatch implements ObjectTargetOpt { + static DefaultHasherSelector defaultHasherSelector() { + return DefaultHasherSelector.INSTANCE; + } + + static final class Crc32cMatch implements ObjectTargetOpt, HasherSelector { private static final long serialVersionUID = 8172282701777561769L; private final int val; @@ -630,6 +638,11 @@ public Mapper bidiWriteObject() { }; } + @Override + public Hasher getHasher() { + return Hasher.noop(); + } + @Override public int hashCode() { return Objects.hash(val); @@ -1316,7 +1329,7 @@ public Mapper listObjects() { } @Deprecated - static final class Md5Match implements ObjectTargetOpt { + static final class Md5Match implements ObjectTargetOpt, HasherSelector { private static final long serialVersionUID = 5237207911268363887L; private final String val; @@ -1359,6 +1372,11 @@ public Mapper bidiWriteObject() { }; } + @Override + public Hasher getHasher() { + return Hasher.noop(); + } + @Override public int hashCode() { return Objects.hash(val); @@ -1984,8 +2002,8 @@ public Mapper listObjects() { } } - static final class UserProject extends RpcOptVal - implements BucketSourceOpt, + interface BucketObjectHmacKeyAllOpt + extends BucketSourceOpt, BucketTargetOpt, BucketListOpt, ObjectSourceOpt, @@ -1994,6 +2012,18 @@ static final class UserProject extends RpcOptVal HmacKeySourceOpt, HmacKeyTargetOpt, HmacKeyListOpt { + @Override + default Mapper rewriteObject() { + return Mapper.identity(); + } + + @Override + default Mapper moveObject() { + return Mapper.identity(); + } + } + + static final class UserProject extends RpcOptVal implements BucketObjectHmacKeyAllOpt { private static final long serialVersionUID = 3962499996741180460L; private UserProject(String val) { @@ -2005,28 +2035,10 @@ public Mapper getGrpcMetadataMapper() { return ctx -> ctx.withExtraHeaders(ImmutableMap.of("X-Goog-User-Project", ImmutableList.of(val))); } - - @Override - public Mapper rewriteObject() { - return Mapper.identity(); - } - - @Override - public Mapper moveObject() { - return Mapper.identity(); - } } static final class Headers extends RpcOptVal> - implements BucketSourceOpt, - BucketTargetOpt, - BucketListOpt, - ObjectSourceOpt, - ObjectTargetOpt, - ObjectListOpt, - HmacKeySourceOpt, - HmacKeyTargetOpt, - HmacKeyListOpt { + implements BucketObjectHmacKeyAllOpt { /** * The set of header names which are blocked from being able to be provided for an instance of @@ -2182,16 +2194,6 @@ private void copyEntries( } } } - - @Override - public Mapper rewriteObject() { - return Mapper.identity(); - } - - @Override - public Mapper moveObject() { - return Mapper.identity(); - } } static final class VersionsFilter extends RpcOptVal<@NonNull Boolean> implements ObjectListOpt { @@ -2607,6 +2609,17 @@ public String toString() { } } + static final class DefaultHasherSelector implements HasherSelector, Opt { + private static final DefaultHasherSelector INSTANCE = new DefaultHasherSelector(); + + private DefaultHasherSelector() {} + + @Override + public Hasher getHasher() { + return Hasher.defaultHasher(); + } + } + /** * Internal "collection" class to represent a set of {@link Opt}s, and to provide useful * transformations to individual mappers or to resolve any extractors providing a new instance @@ -2703,6 +2716,22 @@ Opts projectAsSource() { return Utils.mapBuild(builder); } + @VisibleForTesting + HasherSelector getHasherSelector() { + HasherSelector search = defaultHasherSelector(); + Predicate p = isInstanceOf(HasherSelector.class); + for (T opt : opts) { + if (p.test(opt)) { + search = (HasherSelector) opt; + } + } + return search; + } + + Hasher getHasher() { + return getHasherSelector().getHasher(); + } + Mapper grpcMetadataMapper() { return fuseMappers(GrpcMetadataMapper.class, GrpcMetadataMapper::getGrpcMetadataMapper); } @@ -2755,7 +2784,7 @@ Mapper readObjectRequest() { return fuseMappers(ObjectSourceOpt.class, ObjectSourceOpt::readObject); } - public Mapper bidiReadObjectRequest() { + Mapper bidiReadObjectRequest() { return fuseMappers(ObjectSourceOpt.class, ObjectSourceOpt::bidiReadObject); } diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/WriteCtx.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/WriteCtx.java index 9816d4dc0..5539c04ba 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/WriteCtx.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/WriteCtx.java @@ -23,6 +23,7 @@ import com.google.storage.v2.WriteObjectRequest; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; +import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; final class WriteCtx { @@ -31,13 +32,18 @@ final class WriteCtx { private final AtomicLong totalSentBytes; private final AtomicLong confirmedBytes; - private final AtomicReference cumulativeCrc32c; + private final AtomicReference<@Nullable Crc32cLengthKnown> cumulativeCrc32c; - WriteCtx(RequestFactoryT requestFactory) { + private WriteCtx(RequestFactoryT requestFactory, @Nullable Crc32cLengthKnown initialValue) { this.requestFactory = requestFactory; this.totalSentBytes = new AtomicLong(0); this.confirmedBytes = new AtomicLong(0); - this.cumulativeCrc32c = new AtomicReference<>(); + this.cumulativeCrc32c = new AtomicReference<>(initialValue); + } + + static WriteCtx of( + RFT rft, @NonNull Hasher hasher) { + return new WriteCtx<>(rft, hasher.initialValue()); } public RequestFactoryT getRequestFactory() { @@ -56,7 +62,7 @@ public AtomicLong getConfirmedBytes() { return confirmedBytes; } - public AtomicReference getCumulativeCrc32c() { + public AtomicReference<@Nullable Crc32cLengthKnown> getCumulativeCrc32c() { return cumulativeCrc32c; } diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/BufferToDiskThenUploadTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/BufferToDiskThenUploadTest.java index 1c9635227..04ddbd6c1 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/BufferToDiskThenUploadTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/BufferToDiskThenUploadTest.java @@ -22,6 +22,7 @@ import com.google.cloud.storage.BlobWriteSessionConfig.WriterFactory; import com.google.cloud.storage.UnifiedOpts.ObjectTargetOpt; import com.google.cloud.storage.UnifiedOpts.Opts; +import com.google.cloud.storage.it.ChecksummedTestContent; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.WritableByteChannel; @@ -73,4 +74,101 @@ public BlobInfo internalCreateFrom( String xxdExpected = xxd(bytes); assertThat(xxdActual).isEqualTo(xxdExpected); } + + @Test + public void crc32c_default() throws IOException { + Path tempDir = temporaryFolder.newFolder(testName.getMethodName()).toPath(); + + BufferToDiskThenUpload btdtu = BlobWriteSessionConfigs.bufferToDiskThenUpload(tempDir); + TestClock clock = TestClock.tickBy(Instant.EPOCH, Duration.ofSeconds(1)); + WriterFactory factory = btdtu.createFactory(clock); + + BlobInfo blobInfo = BlobInfo.newBuilder("bucket", "object").build(); + ChecksummedTestContent testContent = + ChecksummedTestContent.of(DataGenerator.base64Characters().genBytes(128)); + WritableByteChannelSession writeSession = + factory.writeSession( + new StorageInternal() { + @Override + public BlobInfo internalCreateFrom( + Path path, BlobInfo info, Opts opts) { + assertThat(info.getCrc32c()).isEqualTo(testContent.getCrc32cBase64()); + assertThat(opts) + .isEqualTo(Opts.from(UnifiedOpts.crc32cMatch(testContent.getCrc32c()))); + return info; + } + }, + blobInfo, + Opts.empty()); + + try (WritableByteChannel open = writeSession.open()) { + open.write(ByteBuffer.wrap(testContent.getBytes())); + } + } + + @Test + public void userProvidedCrc32cTakesPriority() throws IOException { + Path tempDir = temporaryFolder.newFolder(testName.getMethodName()).toPath(); + + BufferToDiskThenUpload btdtu = BlobWriteSessionConfigs.bufferToDiskThenUpload(tempDir); + TestClock clock = TestClock.tickBy(Instant.EPOCH, Duration.ofSeconds(1)); + WriterFactory factory = btdtu.createFactory(clock); + + BlobInfo blobInfo = + BlobInfo.newBuilder("bucket", "object") + .setCrc32c(Utils.crc32cCodec.encode(737)) + .setMd5("something") + .build(); + ChecksummedTestContent testContent = + ChecksummedTestContent.of(DataGenerator.base64Characters().genBytes(128)); + Opts origOpts = Opts.from(UnifiedOpts.crc32cMatch(737)); + WritableByteChannelSession writeSession = + factory.writeSession( + new StorageInternal() { + @Override + public BlobInfo internalCreateFrom( + Path path, BlobInfo info, Opts opts) { + assertThat(Utils.crc32cCodec.decode(info.getCrc32c())).isEqualTo(737); + assertThat(opts).isEqualTo(origOpts); + return info; + } + }, + blobInfo, + origOpts); + + try (WritableByteChannel open = writeSession.open()) { + open.write(ByteBuffer.wrap(testContent.getBytes())); + } + } + + @Test + public void userProvidedMd5TakesPriority() throws IOException { + Path tempDir = temporaryFolder.newFolder(testName.getMethodName()).toPath(); + + BufferToDiskThenUpload btdtu = BlobWriteSessionConfigs.bufferToDiskThenUpload(tempDir); + TestClock clock = TestClock.tickBy(Instant.EPOCH, Duration.ofSeconds(1)); + WriterFactory factory = btdtu.createFactory(clock); + + BlobInfo blobInfo = BlobInfo.newBuilder("bucket", "object").setMd5("something").build(); + ChecksummedTestContent testContent = + ChecksummedTestContent.of(DataGenerator.base64Characters().genBytes(128)); + Opts origOpts = Opts.from(UnifiedOpts.md5Match("something")); + WritableByteChannelSession writeSession = + factory.writeSession( + new StorageInternal() { + @Override + public BlobInfo internalCreateFrom( + Path path, BlobInfo info, Opts opts) { + assertThat(info.getMd5()).isEqualTo("something"); + assertThat(opts).isEqualTo(origOpts); + return info; + } + }, + blobInfo, + origOpts); + + try (WritableByteChannel open = writeSession.open()) { + open.write(ByteBuffer.wrap(testContent.getBytes())); + } + } } diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/Crc32cValueTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/Crc32cValueTest.java index 600b1337b..1565e926c 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/Crc32cValueTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/Crc32cValueTest.java @@ -20,9 +20,11 @@ import com.google.cloud.storage.Crc32cValue.Crc32cLengthKnown; import com.google.cloud.storage.Crc32cValue.Crc32cLengthUnknown; +import com.google.cloud.storage.it.ChecksummedTestContent; import com.google.common.hash.HashFunction; import com.google.common.hash.Hashing; import net.jqwik.api.Example; +import org.checkerframework.checker.nullness.qual.NonNull; final class Crc32cValueTest { @@ -67,4 +69,30 @@ public void ensureConcatSatisfiesTheLeftDistributedProperty() { assertThat(nesting.getValue()).isEqualTo(expected); assertThat(mixed.getValue()).isEqualTo(expected); } + + @Example + void zeroDoesNotTransform() { + Crc32cLengthKnown base = + Hasher.enabled().hash(DataGenerator.base64Characters().genByteBuffer(64)); + + assertThat(base.concat(Crc32cValue.zero())).isSameInstanceAs(base); + assertThat(Crc32cValue.zero().concat(base)).isSameInstanceAs(base); + } + + @Example + void nullSafeConcat_isAlwaysNull() { + ChecksummedTestContent testContent = + ChecksummedTestContent.of(DataGenerator.base64Characters().genBytes(2 * 1024 * 1024)); + + Crc32cLengthKnown actual = + testContent.chunkup(373).stream() + .map(Crc32cValueTest::toCrc32cValue) + .reduce(null, Hasher.enabled()::nullSafeConcat); + + assertThat(actual).isNull(); + } + + private static @NonNull Crc32cLengthKnown toCrc32cValue(ChecksummedTestContent testContent) { + return Crc32cValue.of(testContent.getCrc32c(), testContent.getBytes().length); + } } diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/ITGapicUnbufferedChunkedResumableWritableByteChannelTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/ITGapicUnbufferedChunkedResumableWritableByteChannelTest.java index 6108a0b0b..473e73a9c 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/ITGapicUnbufferedChunkedResumableWritableByteChannelTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/ITGapicUnbufferedChunkedResumableWritableByteChannelTest.java @@ -26,13 +26,16 @@ import com.google.api.core.SettableApiFuture; import com.google.api.gax.grpc.GrpcCallContext; +import com.google.cloud.storage.Hasher.GuavaHasher; import com.google.cloud.storage.ITGapicUnbufferedWritableByteChannelTest.DirectWriteService; import com.google.cloud.storage.Retrying.RetrierWithAlg; +import com.google.cloud.storage.it.ChecksummedTestContent; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.protobuf.ByteString; import com.google.storage.v2.ChecksummedData; import com.google.storage.v2.Object; +import com.google.storage.v2.ObjectChecksums; import com.google.storage.v2.StartResumableWriteRequest; import com.google.storage.v2.StartResumableWriteResponse; import com.google.storage.v2.StorageClient; @@ -48,8 +51,9 @@ public final class ITGapicUnbufferedChunkedResumableWritableByteChannelTest { + public static final GuavaHasher HASHER = Hasher.enabled(); private static final ChunkSegmenter CHUNK_SEGMENTER = - new ChunkSegmenter(Hasher.noop(), ByteStringStrategy.copy(), _256KiB, _256KiB); + new ChunkSegmenter(HASHER, ByteStringStrategy.copy(), _256KiB, _256KiB); /** * @@ -94,10 +98,8 @@ public void scenario1() throws Exception { WriteObjectRequest.newBuilder() .setUploadId(uploadId) .setChecksummedData( - ChecksummedData.newBuilder() - .setContent( - ByteString.copyFrom(DataGenerator.base64Characters().genBytes(_256KiB))) - .build()) + ChecksummedTestContent.of(DataGenerator.base64Characters().genBytes(_256KiB)) + .asChecksummedData()) .build(); WriteObjectResponse resp1 = WriteObjectResponse.newBuilder() @@ -115,7 +117,7 @@ public void scenario1() throws Exception { ResumableWrite resumableWrite = getResumableWrite(uploadId); - WriteCtx writeCtx = new WriteCtx<>(resumableWrite); + WriteCtx writeCtx = WriteCtx.of(resumableWrite, HASHER); SettableApiFuture done = SettableApiFuture.create(); //noinspection resource GapicUnbufferedChunkedResumableWritableByteChannel channel = @@ -179,6 +181,7 @@ public void scenario2() throws Exception { WriteObjectRequest.newBuilder() .setUploadId(uploadId) .setWriteOffset(_256KiB) + .setObjectChecksums(ObjectChecksums.newBuilder().setCrc32C(0).build()) .setFinishWrite(true) .build(); WriteObjectResponse resp1 = WriteObjectResponse.newBuilder().setPersistedSize(_512KiB).build(); @@ -194,7 +197,7 @@ public void scenario2() throws Exception { SettableApiFuture done = SettableApiFuture.create(); ResumableWrite resumableWrite = getResumableWrite(uploadId); - WriteCtx writeCtx = new WriteCtx<>(resumableWrite); + WriteCtx writeCtx = WriteCtx.of(resumableWrite, HASHER); writeCtx.getTotalSentBytes().set(_256KiB); writeCtx.getConfirmedBytes().set(_256KiB); @@ -259,6 +262,7 @@ public void scenario3() throws Exception { WriteObjectRequest.newBuilder() .setUploadId(uploadId) .setWriteOffset(_512KiB) + .setObjectChecksums(ObjectChecksums.newBuilder().setCrc32C(0).build()) .setFinishWrite(true) .build(); WriteObjectResponse resp1 = WriteObjectResponse.newBuilder().setPersistedSize(_256KiB).build(); @@ -274,7 +278,7 @@ public void scenario3() throws Exception { SettableApiFuture done = SettableApiFuture.create(); ResumableWrite resumableWrite = getResumableWrite(uploadId); - WriteCtx writeCtx = new WriteCtx<>(resumableWrite); + WriteCtx writeCtx = WriteCtx.of(resumableWrite, HASHER); writeCtx.getTotalSentBytes().set(_512KiB); writeCtx.getConfirmedBytes().set(_512KiB); @@ -339,6 +343,7 @@ public void scenario4() throws Exception { WriteObjectRequest.newBuilder() .setUploadId(uploadId) .setWriteOffset(_256KiB) + .setObjectChecksums(ObjectChecksums.newBuilder().setCrc32C(0).build()) .setFinishWrite(true) .build(); WriteObjectResponse resp1 = @@ -357,7 +362,7 @@ public void scenario4() throws Exception { SettableApiFuture done = SettableApiFuture.create(); ResumableWrite resumableWrite = getResumableWrite(uploadId); - WriteCtx writeCtx = new WriteCtx<>(resumableWrite); + WriteCtx writeCtx = WriteCtx.of(resumableWrite, HASHER); writeCtx.getTotalSentBytes().set(_256KiB); writeCtx.getConfirmedBytes().set(_256KiB); @@ -419,6 +424,7 @@ public void scenario4_1() throws Exception { WriteObjectRequest.newBuilder() .setUploadId(uploadId) .setWriteOffset(_512KiB) + .setObjectChecksums(ObjectChecksums.newBuilder().setCrc32C(0).build()) .setFinishWrite(true) .build(); WriteObjectResponse resp1 = @@ -437,7 +443,7 @@ public void scenario4_1() throws Exception { SettableApiFuture done = SettableApiFuture.create(); ResumableWrite resumableWrite = getResumableWrite(uploadId); - WriteCtx writeCtx = new WriteCtx<>(resumableWrite); + WriteCtx writeCtx = WriteCtx.of(resumableWrite, HASHER); writeCtx.getTotalSentBytes().set(_512KiB); writeCtx.getConfirmedBytes().set(_512KiB); @@ -502,6 +508,7 @@ public void scenario4_2() throws Exception { WriteObjectRequest.newBuilder() .setUploadId(uploadId) .setWriteOffset(_512KiB) + .setObjectChecksums(ObjectChecksums.newBuilder().setCrc32C(0).build()) .setFinishWrite(true) .build(); WriteObjectResponse resp1 = @@ -520,7 +527,7 @@ public void scenario4_2() throws Exception { SettableApiFuture done = SettableApiFuture.create(); ResumableWrite resumableWrite = getResumableWrite(uploadId); - WriteCtx writeCtx = new WriteCtx<>(resumableWrite); + WriteCtx writeCtx = WriteCtx.of(resumableWrite, HASHER); writeCtx.getTotalSentBytes().set(_512KiB); writeCtx.getConfirmedBytes().set(_512KiB); @@ -586,9 +593,8 @@ public void scenario5() throws Exception { .setUploadId(uploadId) .setWriteOffset(_256KiB) .setChecksummedData( - ChecksummedData.newBuilder() - .setContent( - ByteString.copyFrom(DataGenerator.base64Characters().genBytes(_256KiB)))) + ChecksummedTestContent.of(DataGenerator.base64Characters().genBytes(_256KiB)) + .asChecksummedData()) .build(); StorageImplBase service1 = new DirectWriteService( @@ -611,7 +617,7 @@ public void scenario5() throws Exception { SettableApiFuture done = SettableApiFuture.create(); ResumableWrite resumableWrite = getResumableWrite(uploadId); - WriteCtx writeCtx = new WriteCtx<>(resumableWrite); + WriteCtx writeCtx = WriteCtx.of(resumableWrite, HASHER); writeCtx.getTotalSentBytes().set(_256KiB); writeCtx.getConfirmedBytes().set(_256KiB); @@ -656,10 +662,8 @@ public void scenario7() throws Exception { WriteObjectRequest.newBuilder() .setUploadId(uploadId) .setChecksummedData( - ChecksummedData.newBuilder() - .setContent( - ByteString.copyFrom(DataGenerator.base64Characters().genBytes(_256KiB))) - .build()) + ChecksummedTestContent.of(DataGenerator.base64Characters().genBytes(_256KiB)) + .asChecksummedData()) .build(); WriteObjectResponse resp1 = WriteObjectResponse.newBuilder().setPersistedSize(_512KiB).build(); @@ -674,7 +678,7 @@ public void scenario7() throws Exception { SettableApiFuture done = SettableApiFuture.create(); ResumableWrite resumableWrite = getResumableWrite(uploadId); - WriteCtx writeCtx = new WriteCtx<>(resumableWrite); + WriteCtx writeCtx = WriteCtx.of(resumableWrite, HASHER); //noinspection resource GapicUnbufferedChunkedResumableWritableByteChannel channel = @@ -703,10 +707,8 @@ public void incremental_success() throws Exception { WriteObjectRequest.newBuilder() .setUploadId(uploadId) .setChecksummedData( - ChecksummedData.newBuilder() - .setContent( - ByteString.copyFrom(DataGenerator.base64Characters().genBytes(_256KiB))) - .build()) + ChecksummedTestContent.of(DataGenerator.base64Characters().genBytes(_256KiB)) + .asChecksummedData()) .build(); WriteObjectResponse resp1 = WriteObjectResponse.newBuilder().setPersistedSize(_256KiB).build(); @@ -721,7 +723,7 @@ public void incremental_success() throws Exception { SettableApiFuture done = SettableApiFuture.create(); ResumableWrite resumableWrite = getResumableWrite(uploadId); - WriteCtx writeCtx = new WriteCtx<>(resumableWrite); + WriteCtx writeCtx = WriteCtx.of(resumableWrite, HASHER); //noinspection resource GapicUnbufferedChunkedResumableWritableByteChannel channel = @@ -768,7 +770,7 @@ public void incremental_partialSuccess() throws Exception { SettableApiFuture done = SettableApiFuture.create(); ResumableWrite resumableWrite = getResumableWrite(uploadId); - WriteCtx writeCtx = new WriteCtx<>(resumableWrite); + WriteCtx writeCtx = WriteCtx.of(resumableWrite, HASHER); ChunkSegmenter chunkSegmenter = new ChunkSegmenter(Hasher.noop(), ByteStringStrategy.copy(), _512KiB, _256KiB); diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/ITGapicUnbufferedDirectWritableByteChannelTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/ITGapicUnbufferedDirectWritableByteChannelTest.java index 4a70e9a2e..e8b9cd7d3 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/ITGapicUnbufferedDirectWritableByteChannelTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/ITGapicUnbufferedDirectWritableByteChannelTest.java @@ -24,12 +24,14 @@ import static org.junit.Assert.assertThrows; import com.google.api.core.SettableApiFuture; +import com.google.cloud.storage.Hasher.GuavaHasher; import com.google.cloud.storage.ITGapicUnbufferedWritableByteChannelTest.DirectWriteService; import com.google.cloud.storage.WriteCtx.SimpleWriteObjectRequestBuilderFactory; import com.google.cloud.storage.WriteCtx.WriteObjectRequestBuilderFactory; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.storage.v2.Object; +import com.google.storage.v2.ObjectChecksums; import com.google.storage.v2.StorageClient; import com.google.storage.v2.WriteObjectRequest; import com.google.storage.v2.WriteObjectResponse; @@ -39,14 +41,19 @@ public final class ITGapicUnbufferedDirectWritableByteChannelTest { + public static final GuavaHasher HASHER = Hasher.enabled(); private static final ChunkSegmenter CHUNK_SEGMENTER = - new ChunkSegmenter(Hasher.noop(), ByteStringStrategy.copy(), _256KiB, _256KiB); + new ChunkSegmenter(HASHER, ByteStringStrategy.copy(), _256KiB, _256KiB); /** Attempting to finalize, ack equals expected */ @Test public void ack_eq() throws Exception { WriteObjectRequest req1 = - WriteObjectRequest.newBuilder().setWriteOffset(_256KiB).setFinishWrite(true).build(); + WriteObjectRequest.newBuilder() + .setWriteOffset(_256KiB) + .setObjectChecksums(ObjectChecksums.newBuilder().setCrc32C(0).build()) + .setFinishWrite(true) + .build(); WriteObjectResponse resp1 = WriteObjectResponse.newBuilder() .setResource(Object.newBuilder().setName("name").setSize(_256KiB).build()) @@ -63,7 +70,7 @@ public void ack_eq() throws Exception { SettableApiFuture done = SettableApiFuture.create(); WriteCtx writeCtx = - new WriteCtx<>(WriteObjectRequestBuilderFactory.simple(req1)); + WriteCtx.of(WriteObjectRequestBuilderFactory.simple(req1), HASHER); writeCtx.getTotalSentBytes().set(_256KiB); writeCtx.getConfirmedBytes().set(0); @@ -85,7 +92,11 @@ public void ack_eq() throws Exception { @Test public void ack_lt() throws Exception { WriteObjectRequest req1 = - WriteObjectRequest.newBuilder().setWriteOffset(_512KiB).setFinishWrite(true).build(); + WriteObjectRequest.newBuilder() + .setWriteOffset(_512KiB) + .setObjectChecksums(ObjectChecksums.newBuilder().setCrc32C(0).build()) + .setFinishWrite(true) + .build(); WriteObjectResponse resp1 = WriteObjectResponse.newBuilder() .setResource(Object.newBuilder().setName("name").setSize(_256KiB).build()) @@ -102,7 +113,7 @@ public void ack_lt() throws Exception { SettableApiFuture done = SettableApiFuture.create(); WriteCtx writeCtx = - new WriteCtx<>(WriteObjectRequestBuilderFactory.simple(req1)); + WriteCtx.of(WriteObjectRequestBuilderFactory.simple(req1), HASHER); writeCtx.getTotalSentBytes().set(_512KiB); writeCtx.getConfirmedBytes().set(0); @@ -124,7 +135,11 @@ public void ack_lt() throws Exception { @Test public void ack_gt() throws Exception { WriteObjectRequest req1 = - WriteObjectRequest.newBuilder().setWriteOffset(_512KiB).setFinishWrite(true).build(); + WriteObjectRequest.newBuilder() + .setWriteOffset(_512KiB) + .setObjectChecksums(ObjectChecksums.newBuilder().setCrc32C(0).build()) + .setFinishWrite(true) + .build(); WriteObjectResponse resp1 = WriteObjectResponse.newBuilder() .setResource(Object.newBuilder().setName("name").setSize(_768KiB).build()) @@ -141,7 +156,7 @@ public void ack_gt() throws Exception { SettableApiFuture done = SettableApiFuture.create(); WriteCtx writeCtx = - new WriteCtx<>(WriteObjectRequestBuilderFactory.simple(req1)); + WriteCtx.of(WriteObjectRequestBuilderFactory.simple(req1), HASHER); writeCtx.getTotalSentBytes().set(_512KiB); writeCtx.getConfirmedBytes().set(0); diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/ITGapicUnbufferedFinalizeOnCloseResumableWritableByteChannelTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/ITGapicUnbufferedFinalizeOnCloseResumableWritableByteChannelTest.java index 8181bd2bc..e9dd60f7f 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/ITGapicUnbufferedFinalizeOnCloseResumableWritableByteChannelTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/ITGapicUnbufferedFinalizeOnCloseResumableWritableByteChannelTest.java @@ -24,10 +24,12 @@ import static org.junit.Assert.assertThrows; import com.google.api.core.SettableApiFuture; +import com.google.cloud.storage.Hasher.GuavaHasher; import com.google.cloud.storage.ITGapicUnbufferedWritableByteChannelTest.DirectWriteService; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.storage.v2.Object; +import com.google.storage.v2.ObjectChecksums; import com.google.storage.v2.StartResumableWriteRequest; import com.google.storage.v2.StartResumableWriteResponse; import com.google.storage.v2.StorageClient; @@ -40,8 +42,9 @@ public final class ITGapicUnbufferedFinalizeOnCloseResumableWritableByteChannelTest { + public static final GuavaHasher HASHER = Hasher.enabled(); private static final ChunkSegmenter CHUNK_SEGMENTER = - new ChunkSegmenter(Hasher.noop(), ByteStringStrategy.copy(), _256KiB, _256KiB); + new ChunkSegmenter(HASHER, ByteStringStrategy.copy(), _256KiB, _256KiB); @Test public void incrementalResponseForFinalizingRequest() throws Exception { @@ -50,6 +53,7 @@ public void incrementalResponseForFinalizingRequest() throws Exception { WriteObjectRequest.newBuilder() .setUploadId(uploadId) .setWriteOffset(_512KiB) + .setObjectChecksums(ObjectChecksums.newBuilder().setCrc32C(0).build()) .setFinishWrite(true) .build(); WriteObjectResponse resp1 = WriteObjectResponse.newBuilder().setPersistedSize(_256KiB).build(); @@ -65,7 +69,7 @@ public void incrementalResponseForFinalizingRequest() throws Exception { SettableApiFuture done = SettableApiFuture.create(); ResumableWrite resumableWrite = getResumableWrite(uploadId); - WriteCtx writeCtx = new WriteCtx<>(resumableWrite); + WriteCtx writeCtx = WriteCtx.of(resumableWrite, HASHER); writeCtx.getTotalSentBytes().set(_512KiB); writeCtx.getConfirmedBytes().set(0); @@ -75,7 +79,6 @@ public void incrementalResponseForFinalizingRequest() throws Exception { done, CHUNK_SEGMENTER, storageClient.writeObjectCallable(), writeCtx); StorageException se = assertThrows(StorageException.class, channel::close); - se.printStackTrace(System.out); assertAll( () -> assertThat(se.getCode()).isEqualTo(0), () -> assertThat(se.getReason()).isEqualTo("invalid"), @@ -127,6 +130,7 @@ public void scenario4() throws Exception { WriteObjectRequest.newBuilder() .setUploadId(uploadId) .setWriteOffset(_256KiB) + .setObjectChecksums(ObjectChecksums.newBuilder().setCrc32C(0).build()) .setFinishWrite(true) .build(); WriteObjectResponse resp1 = @@ -145,7 +149,7 @@ public void scenario4() throws Exception { SettableApiFuture done = SettableApiFuture.create(); ResumableWrite resumableWrite = getResumableWrite(uploadId); - WriteCtx writeCtx = new WriteCtx<>(resumableWrite); + WriteCtx writeCtx = WriteCtx.of(resumableWrite, HASHER); writeCtx.getTotalSentBytes().set(_256KiB); writeCtx.getConfirmedBytes().set(0); @@ -203,6 +207,7 @@ public void scenario4_1() throws Exception { WriteObjectRequest.newBuilder() .setUploadId(uploadId) .setWriteOffset(_512KiB) + .setObjectChecksums(ObjectChecksums.newBuilder().setCrc32C(0).build()) .setFinishWrite(true) .build(); WriteObjectResponse resp1 = @@ -221,7 +226,7 @@ public void scenario4_1() throws Exception { SettableApiFuture done = SettableApiFuture.create(); ResumableWrite resumableWrite = getResumableWrite(uploadId); - WriteCtx writeCtx = new WriteCtx<>(resumableWrite); + WriteCtx writeCtx = WriteCtx.of(resumableWrite, HASHER); writeCtx.getTotalSentBytes().set(_512KiB); writeCtx.getConfirmedBytes().set(0); @@ -231,7 +236,6 @@ public void scenario4_1() throws Exception { done, CHUNK_SEGMENTER, storageClient.writeObjectCallable(), writeCtx); StorageException se = assertThrows(StorageException.class, channel::close); - se.printStackTrace(System.out); assertAll( () -> assertThat(se.getCode()).isEqualTo(0), () -> assertThat(se.getReason()).isEqualTo("dataLoss"), @@ -282,6 +286,7 @@ public void scenario4_2() throws Exception { WriteObjectRequest.newBuilder() .setUploadId(uploadId) .setWriteOffset(_512KiB) + .setObjectChecksums(ObjectChecksums.newBuilder().setCrc32C(0).build()) .setFinishWrite(true) .build(); WriteObjectResponse resp1 = @@ -300,7 +305,7 @@ public void scenario4_2() throws Exception { SettableApiFuture done = SettableApiFuture.create(); ResumableWrite resumableWrite = getResumableWrite(uploadId); - WriteCtx writeCtx = new WriteCtx<>(resumableWrite); + WriteCtx writeCtx = WriteCtx.of(resumableWrite, HASHER); writeCtx.getTotalSentBytes().set(_512KiB); writeCtx.getConfirmedBytes().set(0); @@ -310,7 +315,6 @@ public void scenario4_2() throws Exception { done, CHUNK_SEGMENTER, storageClient.writeObjectCallable(), writeCtx); StorageException se = assertThrows(StorageException.class, channel::close); - se.printStackTrace(System.out); assertAll( () -> assertThat(se.getCode()).isEqualTo(0), () -> assertThat(se.getReason()).isEqualTo("dataLoss"), diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/ITGapicUnbufferedWritableByteChannelTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/ITGapicUnbufferedWritableByteChannelTest.java index a31fc0c33..e23b2a57f 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/ITGapicUnbufferedWritableByteChannelTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/ITGapicUnbufferedWritableByteChannelTest.java @@ -159,7 +159,7 @@ public void directUpload() throws IOException, InterruptedException, ExecutionEx SettableApiFuture result = SettableApiFuture.create(); try (GapicUnbufferedDirectWritableByteChannel c = new GapicUnbufferedDirectWritableByteChannel( - result, segmenter, sc.writeObjectCallable(), new WriteCtx<>(reqFactory))) { + result, segmenter, sc.writeObjectCallable(), WriteCtx.of(reqFactory, HASHER))) { c.write(ByteBuffer.wrap(bytes)); } assertThat(result.get()).isEqualTo(resp); @@ -185,7 +185,7 @@ public void resumableUpload() throws IOException, InterruptedException, Executio result, segmenter, sc.writeObjectCallable(), - new WriteCtx<>(reqFactory), + WriteCtx.of(reqFactory, HASHER), RetrierWithAlg.attemptOnce(), Retrying::newCallContext); ArrayList debugMessages = new ArrayList<>(); @@ -267,7 +267,7 @@ public void resumableUpload_chunkAutomaticRetry() result, segmenter, sc.writeObjectCallable(), - new WriteCtx<>(reqFactory), + WriteCtx.of(reqFactory, HASHER), TestUtils.retrierFromStorageOptions(fake.getGrpcStorageOptions()) .withAlg(Retrying.alwaysRetry()), Retrying::newCallContext)) { @@ -319,7 +319,7 @@ public void resumableUpload_finalizeWhenWriteAndCloseCalledEvenWhenQuantumAligne result, segmenter, sc.writeObjectCallable(), - new WriteCtx<>(reqFactory), + WriteCtx.of(reqFactory, HASHER), RetrierWithAlg.attemptOnce(), Retrying::newCallContext); try { diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/ITSyncAndUploadUnbufferedWritableByteChannelPropertyTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/ITSyncAndUploadUnbufferedWritableByteChannelPropertyTest.java index fd4f0fd58..2d55a26cb 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/ITSyncAndUploadUnbufferedWritableByteChannelPropertyTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/ITSyncAndUploadUnbufferedWritableByteChannelPropertyTest.java @@ -47,6 +47,7 @@ import com.google.protobuf.ByteString; import com.google.protobuf.Message; import com.google.protobuf.TextFormat; +import com.google.storage.v2.ChecksummedData; import com.google.storage.v2.Object; import com.google.storage.v2.ObjectChecksums; import com.google.storage.v2.QueryWriteStatusRequest; @@ -63,11 +64,8 @@ import io.grpc.stub.StreamObserver; import java.io.IOException; import java.nio.ByteBuffer; -import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collections; @@ -124,23 +122,7 @@ static void beforeContainer() throws IOException { @AfterContainer static void afterContainer() throws IOException { if (tmpFolder != null) { - Files.walkFileTree( - tmpFolder, - new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) - throws IOException { - Files.deleteIfExists(file); - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult postVisitDirectory(Path dir, IOException exc) - throws IOException { - Files.deleteIfExists(dir); - return FileVisitResult.CONTINUE; - } - }); + TestUtils.rmDashRf(tmpFolder); } } @@ -356,7 +338,7 @@ void testUploads(@ForAll("scenario") Scenario s) throws Exception { // TestUtils.defaultRetrier(), new DefaultRetrier(UnaryOperator.identity(), defaultRetryingDeps()), StorageRetryStrategy.getDefaultStorageRetryStrategy().getIdempotentHandler(), - new WriteCtx<>(resumableWrite), + WriteCtx.of(resumableWrite, s.chunkSegmenter.getHasher()), rf, s.copyBuffer); try (BufferedWritableByteChannel w = s.buffered(syncAndUpload)) { @@ -550,19 +532,22 @@ private void unexpected(StreamObserver respond, Message msg) { BlobInfo info = BlobInfo.newBuilder("b", "o").build(); SettableApiFuture resultFuture = SettableApiFuture.create(); BufferHandle recoverBufferHandle = BufferHandle.allocate(2); + ChunkSegmenter chunkSegmenter = + new ChunkSegmenter(Hasher.enabled(), ByteStringStrategy.copy(), 2, 2); SyncAndUploadUnbufferedWritableByteChannel syncAndUpload = new SyncAndUploadUnbufferedWritableByteChannel( storage.storageClient.writeObjectCallable(), storage.storageClient.queryWriteStatusCallable(), resultFuture, - new ChunkSegmenter(Hasher.enabled(), ByteStringStrategy.copy(), 2, 2), + chunkSegmenter, new DefaultRetrier(UnaryOperator.identity(), storage.getOptions()), StorageRetryStrategy.getDefaultStorageRetryStrategy().getIdempotentHandler(), - new WriteCtx<>( + WriteCtx.of( new ResumableWrite( reqStart, resStart, - id -> reqWrite0.toBuilder().clearWriteObjectSpec().setUploadId(id).build())), + id -> reqWrite0.toBuilder().clearWriteObjectSpec().setUploadId(id).build()), + chunkSegmenter.getHasher()), recoveryFileManager.newRecoveryFile(info), recoverBufferHandle); try (BufferedWritableByteChannel w = @@ -751,7 +736,7 @@ public static Scenario of( .toString(), objectName, objectSize, - new ChunkSegmenter(Hasher.noop(), ByteStringStrategy.copy(), segmentSize, quantum), + new ChunkSegmenter(Hasher.enabled(), ByteStringStrategy.copy(), segmentSize, quantum), BufferHandle.allocate(segmentSize), BufferHandle.allocate(segmentSize), failuresQueue, @@ -1008,6 +993,25 @@ public FailureInducingWriteObjectRequestObserver( @Override public void onNext(WriteObjectRequest writeObjectRequest) { + if (writeObjectRequest.hasChecksummedData()) { + ChecksummedData checksummedData = writeObjectRequest.getChecksummedData(); + if (!checksummedData.hasCrc32C()) { + errored = true; + sendFailure("no crc32c value specified"); + return; + } + if (!checksummedData.getContent().isEmpty() && checksummedData.getCrc32C() == 0) { + errored = true; + sendFailure("crc32c value of 0 with non-empty content"); + return; + } + } + if (writeObjectRequest.hasObjectChecksums() + && !writeObjectRequest.getObjectChecksums().hasCrc32C()) { + errored = true; + sendFailure("missing object_checksums.crc32c"); + return; + } if (ctx == null) { UploadId uploadId = UploadId.of(writeObjectRequest.getUploadId()); if (data.containsKey(uploadId)) { @@ -1050,6 +1054,11 @@ public void onCompleted() { responseObserver.onNext(resp); responseObserver.onCompleted(); } + + private void sendFailure(String description) { + responseObserver.onError( + Code.INVALID_ARGUMENT.toStatus().withDescription(description).asRuntimeException()); + } } @FunctionalInterface diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/ParallelCompositeUploadWritableByteChannelTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/ParallelCompositeUploadWritableByteChannelTest.java index a4902111f..14e9ef1ec 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/ParallelCompositeUploadWritableByteChannelTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/ParallelCompositeUploadWritableByteChannelTest.java @@ -892,7 +892,8 @@ public BlobInfo compose(ComposeRequest composeRequest) { .map(Data::getCrc32c) .collect(ImmutableList.toImmutableList()); - Crc32cLengthKnown reduce = crc32cs.stream().reduce(null, HASHER::nullSafeConcat); + Crc32cLengthKnown reduce = + crc32cs.stream().reduce(Crc32cValue.zero(), Crc32cLengthKnown::concat); Preconditions.checkState(reduce != null, "unable to compute crc32c for compose request"); b.setCrc32c(Utils.crc32cCodec.encode(reduce.getValue())); BlobInfo gen1 = b.build(); diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java index 036f8203a..bae429597 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java @@ -31,7 +31,6 @@ import com.google.api.services.storage.model.StorageObject; import com.google.cloud.ServiceOptions; import com.google.cloud.Tuple; -import com.google.cloud.storage.Storage.BlobTargetOption; import com.google.cloud.storage.spi.StorageRpcFactory; import com.google.cloud.storage.spi.v1.StorageRpc; import com.google.common.collect.ImmutableList; @@ -103,15 +102,14 @@ public class StorageImplMockitoTest { BlobInfo.newBuilder(BUCKET_NAME1, BLOB_NAME1, 24L) .setMetageneration(PAGE_SIZE) .setContentType("application/json") - .setMd5("md5string") .build(); private static final BlobInfo BLOB_INFO2 = BlobInfo.newBuilder(BUCKET_NAME1, BLOB_NAME2).build(); private static final BlobInfo BLOB_INFO3 = BlobInfo.newBuilder(BUCKET_NAME1, BLOB_NAME3).build(); private static final BlobInfo BLOB_INFO_WITH_HASHES = - BLOB_INFO1.toBuilder().setMd5(CONTENT_MD5).setCrc32c(CONTENT_CRC32C).build(); + BLOB_INFO1.toBuilder().setCrc32c(CONTENT_CRC32C).build(); private static final BlobInfo BLOB_INFO_WITHOUT_HASHES = - BLOB_INFO1.toBuilder().setMd5(null).setCrc32c(null).build(); + BLOB_INFO1.toBuilder().setCrc32c(null).build(); // Empty StorageRpc options private static final Map EMPTY_RPC_OPTIONS = ImmutableMap.of(); @@ -616,213 +614,6 @@ private void verifyCreateBlobCapturedStream(ArgumentCaptor assertEquals(-1, byteStream.read(streamBytes)); } - @Test - public void testCreateBlob() throws IOException { - ArgumentCaptor capturedStream = - ArgumentCaptor.forClass(ByteArrayInputStream.class); - doReturn(Conversions.json().blobInfo().encode(BLOB_INFO1)) - .doThrow(UNEXPECTED_CALL_EXCEPTION) - .when(storageRpcMock) - .create( - Mockito.eq(Conversions.json().blobInfo().encode(BLOB_INFO_WITH_HASHES)), - capturedStream.capture(), - Mockito.eq(EMPTY_RPC_OPTIONS)); - initializeService(); - - Blob blob = storage.create(BLOB_INFO1, BLOB_CONTENT); - - assertEquals(expectedBlob1, blob); - verifyCreateBlobCapturedStream(capturedStream); - } - - @Test - public void testCreateBlobWithSubArrayFromByteArray() throws IOException { - ArgumentCaptor capturedStream = - ArgumentCaptor.forClass(ByteArrayInputStream.class); - doReturn(Conversions.json().blobInfo().encode(BLOB_INFO1)) - .doThrow(UNEXPECTED_CALL_EXCEPTION) - .when(storageRpcMock) - .create( - Mockito.eq( - Conversions.json() - .blobInfo() - .encode( - BLOB_INFO1.toBuilder() - .setMd5(SUB_CONTENT_MD5) - .setCrc32c(SUB_CONTENT_CRC32C) - .build())), - capturedStream.capture(), - Mockito.eq(EMPTY_RPC_OPTIONS)); - initializeService(); - - Blob blob = storage.create(BLOB_INFO1, BLOB_CONTENT, 1, 2); - - assertEquals(expectedBlob1, blob); - ByteArrayInputStream byteStream = capturedStream.getValue(); - byte[] streamBytes = new byte[BLOB_SUB_CONTENT.length]; - assertEquals(BLOB_SUB_CONTENT.length, byteStream.read(streamBytes)); - assertArrayEquals(BLOB_SUB_CONTENT, streamBytes); - assertEquals(-1, byteStream.read(streamBytes)); - } - - @Test - public void testCreateBlobRetry() throws IOException { - ArgumentCaptor capturedStream = - ArgumentCaptor.forClass(ByteArrayInputStream.class); - - StorageObject storageObject = Conversions.json().blobInfo().encode(BLOB_INFO_WITH_HASHES); - - doThrow(new StorageException(500, "internalError")) - .doReturn(Conversions.json().blobInfo().encode(BLOB_INFO1)) - .doThrow(UNEXPECTED_CALL_EXCEPTION) - .when(storageRpcMock) - .create( - Mockito.eq(storageObject), - capturedStream.capture(), - Mockito.eq(BLOB_INFO1_RPC_OPTIONS_WITH_GENERATION)); - - storage = - options.toBuilder() - .setRetrySettings(ServiceOptions.getDefaultRetrySettings()) - .build() - .getService(); - initializeServiceDependentObjects(); - - Blob blob = storage.create(BLOB_INFO1, BLOB_CONTENT, BlobTargetOption.generationMatch()); - - assertEquals(expectedBlob1, blob); - - byte[] streamBytes = new byte[BLOB_CONTENT.length]; - for (ByteArrayInputStream byteStream : capturedStream.getAllValues()) { - assertEquals(BLOB_CONTENT.length, byteStream.read(streamBytes)); - assertArrayEquals(BLOB_CONTENT, streamBytes); - assertEquals(-1, byteStream.read(streamBytes)); - } - } - - @Test - public void testCreateEmptyBlob() throws IOException { - ArgumentCaptor capturedStream = - ArgumentCaptor.forClass(ByteArrayInputStream.class); - - doReturn(Conversions.json().blobInfo().encode(BLOB_INFO1)) - .doThrow(UNEXPECTED_CALL_EXCEPTION) - .when(storageRpcMock) - .create( - Mockito.eq( - Conversions.json() - .blobInfo() - .encode( - BLOB_INFO1.toBuilder() - .setMd5("1B2M2Y8AsgTpgAmY7PhCfg==") - .setCrc32c("AAAAAA==") - .build())), - capturedStream.capture(), - Mockito.eq(EMPTY_RPC_OPTIONS)); - initializeService(); - - Blob blob = storage.create(BLOB_INFO1); - assertEquals(expectedBlob1, blob); - ByteArrayInputStream byteStream = capturedStream.getValue(); - byte[] streamBytes = new byte[BLOB_CONTENT.length]; - assertEquals(-1, byteStream.read(streamBytes)); - } - - @Test - public void testCreateBlobWithOptions() throws IOException { - ArgumentCaptor capturedStream = - ArgumentCaptor.forClass(ByteArrayInputStream.class); - - doReturn(Conversions.json().blobInfo().encode(BLOB_INFO1)) - .doThrow(UNEXPECTED_CALL_EXCEPTION) - .when(storageRpcMock) - .create( - Mockito.eq(Conversions.json().blobInfo().encode(BLOB_INFO_WITH_HASHES)), - capturedStream.capture(), - Mockito.eq(BLOB_TARGET_OPTIONS_CREATE)); - initializeService(); - - Blob blob = - storage.create( - BLOB_INFO1, - BLOB_CONTENT, - BLOB_TARGET_METAGENERATION, - BLOB_TARGET_NOT_EXIST, - BLOB_TARGET_PREDEFINED_ACL); - assertEquals(expectedBlob1, blob); - verifyCreateBlobCapturedStream(capturedStream); - } - - @Test - public void testCreateBlobWithDisabledGzipContent() throws IOException { - ArgumentCaptor capturedStream = - ArgumentCaptor.forClass(ByteArrayInputStream.class); - - doReturn(Conversions.json().blobInfo().encode(BLOB_INFO1)) - .doThrow(UNEXPECTED_CALL_EXCEPTION) - .when(storageRpcMock) - .create( - Mockito.eq(Conversions.json().blobInfo().encode(BLOB_INFO_WITH_HASHES)), - capturedStream.capture(), - Mockito.eq(BLOB_TARGET_OPTIONS_CREATE_DISABLE_GZIP_CONTENT)); - initializeService(); - - Blob blob = storage.create(BLOB_INFO1, BLOB_CONTENT, BLOB_TARGET_DISABLE_GZIP_CONTENT); - assertEquals(expectedBlob1, blob); - verifyCreateBlobCapturedStream(capturedStream); - } - - @Test - public void testCreateBlobWithEncryptionKey() throws IOException { - ArgumentCaptor capturedStream = - ArgumentCaptor.forClass(ByteArrayInputStream.class); - - doReturn(Conversions.json().blobInfo().encode(BLOB_INFO1)) - .doReturn(Conversions.json().blobInfo().encode(BLOB_INFO1)) - .doThrow(UNEXPECTED_CALL_EXCEPTION) - .when(storageRpcMock) - .create( - Mockito.eq(Conversions.json().blobInfo().encode(BLOB_INFO_WITH_HASHES)), - capturedStream.capture(), - Mockito.eq(ENCRYPTION_KEY_OPTIONS)); - initializeService(); - - Blob blob = - storage.create(BLOB_INFO1, BLOB_CONTENT, Storage.BlobTargetOption.encryptionKey(KEY)); - assertEquals(expectedBlob1, blob); - verifyCreateBlobCapturedStream(capturedStream); - blob = - storage.create( - BLOB_INFO1, BLOB_CONTENT, Storage.BlobTargetOption.encryptionKey(BASE64_KEY)); - assertEquals(expectedBlob1, blob); - verifyCreateBlobCapturedStream(capturedStream); - } - - @Test - public void testCreateBlobWithKmsKeyName() throws IOException { - ArgumentCaptor capturedStream = - ArgumentCaptor.forClass(ByteArrayInputStream.class); - - doReturn(Conversions.json().blobInfo().encode(BLOB_INFO1)) - .doReturn(Conversions.json().blobInfo().encode(BLOB_INFO1)) - .doThrow(UNEXPECTED_CALL_EXCEPTION) - .when(storageRpcMock) - .create( - Mockito.eq(Conversions.json().blobInfo().encode(BLOB_INFO_WITH_HASHES)), - capturedStream.capture(), - Mockito.eq(KMS_KEY_NAME_OPTIONS)); - initializeService(); - - Blob blob = - storage.create(BLOB_INFO1, BLOB_CONTENT, Storage.BlobTargetOption.kmsKeyName(KMS_KEY_NAME)); - assertEquals(expectedBlob1, blob); - verifyCreateBlobCapturedStream(capturedStream); - blob = - storage.create(BLOB_INFO1, BLOB_CONTENT, Storage.BlobTargetOption.kmsKeyName(KMS_KEY_NAME)); - assertEquals(expectedBlob1, blob); - verifyCreateBlobCapturedStream(capturedStream); - } - @Test @SuppressWarnings({"unchecked", "deprecation"}) public void testCreateBlobFromStream() throws IOException { diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/TestUtils.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/TestUtils.java index c501d11b0..5fd68dfc8 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/TestUtils.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/TestUtils.java @@ -53,6 +53,10 @@ import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; +import java.nio.file.FileVisitResult; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; @@ -374,4 +378,23 @@ private static String messagesToText(Throwable t, String indent) { .flatMap(s -> s) .collect(Collectors.joining("\n")); } + + public static void rmDashRf(Path path) throws IOException { + java.nio.file.Files.walkFileTree( + path, + new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) + throws IOException { + java.nio.file.Files.deleteIfExists(file); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { + java.nio.file.Files.deleteIfExists(dir); + return FileVisitResult.CONTINUE; + } + }); + } } diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/TmpDir.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/TmpDir.java new file mode 100644 index 000000000..4cc29eac8 --- /dev/null +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/TmpDir.java @@ -0,0 +1,59 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.storage; + +import com.google.common.base.MoreObjects; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class TmpDir implements AutoCloseable { + private static final Logger LOGGER = LoggerFactory.getLogger(TmpDir.class); + + private final Path path; + + private TmpDir(Path path) { + this.path = path; + } + + public Path getPath() { + return path; + } + + /** Delete the TmpFile this handle is holding */ + @Override + public void close() throws IOException { + TestUtils.rmDashRf(path); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this).add("path", path).toString(); + } + + /** + * Create a temporary file, which will be deleted when close is called on the returned {@link + * TmpDir} + */ + public static TmpDir of(Path baseDir, String prefix) throws IOException { + LOGGER.trace("of(baseDir : {}, prefix : {})", baseDir, prefix); + Path path = Files.createTempDirectory(baseDir, prefix); + return new TmpDir(path); + } +} diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/UnifiedOptsTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/UnifiedOptsTest.java index 73d88580a..e5a38b436 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/UnifiedOptsTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/UnifiedOptsTest.java @@ -20,6 +20,10 @@ import static com.google.common.truth.Truth.assertWithMessage; import static org.junit.Assert.assertThrows; +import com.google.cloud.storage.UnifiedOpts.Crc32cMatch; +import com.google.cloud.storage.UnifiedOpts.DefaultHasherSelector; +import com.google.cloud.storage.UnifiedOpts.HasherSelector; +import com.google.cloud.storage.UnifiedOpts.Md5Match; import com.google.cloud.storage.UnifiedOpts.ObjectSourceOpt; import com.google.cloud.storage.UnifiedOpts.ObjectTargetOpt; import com.google.cloud.storage.UnifiedOpts.Opt; @@ -146,6 +150,27 @@ public void validateFactoryMethodEnforceNonNull_storage_updateHmacKeyOption() th validateFactoryMethodEnforceNonNull(Storage.UpdateHmacKeyOption.class); } + @Test + public void getHasher_selectsLastValue() { + DefaultHasherSelector first = UnifiedOpts.defaultHasherSelector(); + Md5Match second = UnifiedOpts.md5Match("asdf"); + Crc32cMatch third = UnifiedOpts.crc32cMatch(3); + Opts hasherOpts = Opts.from(first, second, third); + + HasherSelector actual = hasherOpts.getHasherSelector(); + assertThat(actual).isSameInstanceAs(third); + } + + @Test + public void hasher_md5Match_noop() { + assertThat(UnifiedOpts.md5Match("xyz").getHasher()).isEqualTo(Hasher.noop()); + } + + @Test + public void hasher_crc32cMatch_noop() { + assertThat(UnifiedOpts.crc32cMatch(77).getHasher()).isEqualTo(Hasher.noop()); + } + @Test public void transformTo() { SecretKey key = @@ -172,8 +197,8 @@ public byte[] getEncoded() { UnifiedOpts.encryptionKey(key), // userProject implements both target and source UnifiedOpts.userProject("user-project"), - // crc32c is not a source opt or a ProjectToSource opt, it should be excluded - UnifiedOpts.crc32cMatch(1)); + // contentType is not a source opt or a ProjectToSource opt, it should be excluded + UnifiedOpts.setContentType("application/octet-stream")); Opts sourceOpts = targetOpts.transformTo(ObjectSourceOpt.class); Opts expected = diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ChecksummedTestContent.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ChecksummedTestContent.java index aa87e6478..6ccb05f52 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ChecksummedTestContent.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ChecksummedTestContent.java @@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkPositionIndexes; import com.google.common.base.MoreObjects; +import com.google.common.collect.ImmutableList; import com.google.common.hash.Hashing; import com.google.common.io.BaseEncoding; import com.google.common.primitives.Ints; @@ -28,8 +29,10 @@ import com.google.storage.v2.ChecksummedData; import java.io.ByteArrayInputStream; import java.nio.charset.StandardCharsets; +import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; +import java.util.List; public final class ChecksummedTestContent { @@ -100,12 +103,19 @@ public ChecksummedTestContent slice(int begin, int length) { return of(bytes, begin, Math.min(length, bytes.length - begin)); } + public List chunkup(int chunkSize) { + List elements = new ArrayList<>(); + for (int i = 0; i < bytes.length; i += chunkSize) { + elements.add(slice(i, chunkSize)); + } + return ImmutableList.copyOf(elements); + } + @Override public String toString() { return MoreObjects.toStringHelper(this) .add("byteCount", bytes.length) - .add("crc32c", crc32c) - .add("md5Base64", md5Base64) + .add("crc32c", Integer.toUnsignedString(crc32c)) .toString(); } diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBlobWriteSessionCommonSemanticsTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBlobWriteSessionCommonSemanticsTest.java index dc02c3fb9..663a3b1de 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBlobWriteSessionCommonSemanticsTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBlobWriteSessionCommonSemanticsTest.java @@ -19,6 +19,7 @@ import static com.google.cloud.storage.TestUtils.assertAll; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; +import static org.junit.Assume.assumeFalse; import static org.junit.Assume.assumeTrue; import com.google.cloud.storage.BlobInfo; @@ -26,6 +27,7 @@ import com.google.cloud.storage.BlobWriteSessionConfig; import com.google.cloud.storage.BlobWriteSessionConfigs; import com.google.cloud.storage.BucketInfo; +import com.google.cloud.storage.DataGenerator; import com.google.cloud.storage.ParallelCompositeUploadBlobWriteSessionConfig.BufferAllocationStrategy; import com.google.cloud.storage.ParallelCompositeUploadBlobWriteSessionConfig.ExecutorSupplier; import com.google.cloud.storage.ParallelCompositeUploadBlobWriteSessionConfig.PartCleanupStrategy; @@ -179,6 +181,51 @@ public void getResultErrorsWhenTheSessionErrors() throws Exception { () -> assertThat(((StorageException) resultSe.getCause()).getCode()).isEqualTo(412)); } + @Test + public void userProvidedCrc32cValueIsRespected() throws IOException { + assumeFalse("b/226975500", params.desc.startsWith("p")); + ChecksummedTestContent testContent = + ChecksummedTestContent.of(DataGenerator.base64Characters().genBytes(5 * 1024 * 1024 + 17)); + ChecksummedTestContent missingAByte = testContent.slice(0, testContent.getBytes().length - 1); + + BlobInfo info = + BlobInfo.newBuilder(bucket, generator.randomObjectName()) + .setCrc32c(missingAByte.getCrc32cBase64()) + .build(); + BlobWriteSession session = + storage.blobWriteSession( + info, BlobWriteOption.crc32cMatch(), BlobWriteOption.doesNotExist()); + WritableByteChannel open = session.open(); + try { + open.write(ByteBuffer.wrap(testContent.getBytes())); + } finally { + StorageException se = assertThrows(StorageException.class, () -> open.close()); + assertThat(se.getCode()).isEqualTo(400); + } + } + + @Test + public void userProvidedMd5ValueIsRespected() throws IOException { + assumeFalse("b/226975500", params.desc.startsWith("p")); + ChecksummedTestContent testContent = + ChecksummedTestContent.of(DataGenerator.base64Characters().genBytes(5 * 1024 * 1024 + 17)); + ChecksummedTestContent missingAByte = testContent.slice(0, testContent.getBytes().length - 1); + + BlobInfo info = + BlobInfo.newBuilder(bucket, generator.randomObjectName()) + .setMd5(missingAByte.getMd5Base64()) + .build(); + BlobWriteSession session = + storage.blobWriteSession(info, BlobWriteOption.md5Match(), BlobWriteOption.doesNotExist()); + WritableByteChannel open = session.open(); + try { + open.write(ByteBuffer.wrap(testContent.getBytes())); + } finally { + StorageException se = assertThrows(StorageException.class, () -> open.close()); + assertThat(se.getCode()).isEqualTo(400); + } + } + public static final class ParamsProvider implements ParametersProvider { @Override public ImmutableList parameters() { diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITObjectChecksumSupportTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITObjectChecksumSupportTest.java index da0c50452..5153ea127 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITObjectChecksumSupportTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITObjectChecksumSupportTest.java @@ -31,6 +31,7 @@ import com.google.cloud.storage.Storage.BlobWriteOption; import com.google.cloud.storage.StorageException; import com.google.cloud.storage.StorageOptions; +import com.google.cloud.storage.TmpDir; import com.google.cloud.storage.TmpFile; import com.google.cloud.storage.TransportCompatibility.Transport; import com.google.cloud.storage.it.ITObjectChecksumSupportTest.ChecksummedTestContentProvider; @@ -54,7 +55,9 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.concurrent.TimeUnit; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestName; import org.junit.runner.RunWith; @RunWith(StorageITRunner.class) @@ -75,6 +78,8 @@ public final class ITObjectChecksumSupportTest { @Parameter public ChecksummedTestContent content; + @Rule public final TestName testName = new TestName(); + public static final class ChecksummedTestContentProvider implements ParametersProvider { @Override @@ -85,6 +90,8 @@ public ImmutableList parameters() { int _24MiB = 24 * 1024 * 1024; return ImmutableList.of( + // empty object content + ChecksummedTestContent.of(new byte[0]), // small, single message single stream when resumable ChecksummedTestContent.of(gen.genBytes(15)), // med, multiple messages single stream when resumable @@ -349,4 +356,69 @@ public void testCrc32cValidated_bidiWrite_expectFailure() throws Exception { assertThat(expected.getCode()).isEqualTo(400); } } + + @Test + @CrossRun.Exclude(transports = Transport.HTTP) + public void testCrc32cValidated_journaling_expectSuccess() throws Exception { + String blobName = generator.randomObjectName(); + BlobId blobId = BlobId.of(bucket.getName(), blobName); + BlobInfo blobInfo = BlobInfo.newBuilder(blobId).setCrc32c(content.getCrc32cBase64()).build(); + + byte[] bytes = content.getBytes(); + + try (TmpDir journalingDir = TmpDir.of(tmpDir, testName.getMethodName())) { + StorageOptions options = + this.storage.getOptions().toBuilder() + .setBlobWriteSessionConfig( + BlobWriteSessionConfigs.journaling(ImmutableList.of(journalingDir.getPath()))) + .build(); + + try (Storage storage = options.getService()) { + BlobWriteSession session = + storage.blobWriteSession( + blobInfo, BlobWriteOption.doesNotExist(), BlobWriteOption.crc32cMatch()); + + try (ReadableByteChannel src = Channels.newChannel(new ByteArrayInputStream(bytes)); + WritableByteChannel dst = session.open()) { + ByteStreams.copy(src, dst); + } + + BlobInfo gen1 = session.getResult().get(5, TimeUnit.SECONDS); + assertThat(gen1.getCrc32c()).isEqualTo(content.getCrc32cBase64()); + } + } + } + + @Test + @CrossRun.Exclude(transports = Transport.HTTP) + public void testCrc32cValidated_journaling_expectFailure() throws Exception { + String blobName = generator.randomObjectName(); + BlobId blobId = BlobId.of(bucket.getName(), blobName); + BlobInfo blobInfo = BlobInfo.newBuilder(blobId).setCrc32c(content.getCrc32cBase64()).build(); + + byte[] bytes = content.concat('x'); + + try (TmpDir journalingDir = TmpDir.of(tmpDir, generator.randomObjectName())) { + StorageOptions options = + this.storage.getOptions().toBuilder() + .setBlobWriteSessionConfig( + BlobWriteSessionConfigs.journaling(ImmutableList.of(journalingDir.getPath()))) + .build(); + + try (Storage storage = options.getService()) { + BlobWriteSession session = + storage.blobWriteSession( + blobInfo, BlobWriteOption.doesNotExist(), BlobWriteOption.crc32cMatch()); + + WritableByteChannel dst = session.open(); + try (ReadableByteChannel src = Channels.newChannel(new ByteArrayInputStream(bytes))) { + ByteStreams.copy(src, dst); + } + + StorageException expected = assertThrows(StorageException.class, dst::close); + + assertThat(expected.getCode()).isEqualTo(400); + } + } + } } From a1dda0249e76c3eaa33de65427a7db6151401564 Mon Sep 17 00:00:00 2001 From: Diego Marquez Date: Thu, 24 Jul 2025 13:12:52 -0400 Subject: [PATCH 12/15] chore: manual update of update_generation_config.sh (#3205) Unfortunately, https://github.com/googleapis/sdk-platform-java/pull/3853 cannot be automatically propagated. This PR manually updates this script with the latest. --- .github/scripts/update_generation_config.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/scripts/update_generation_config.sh b/.github/scripts/update_generation_config.sh index fff56bf5d..92efcf881 100644 --- a/.github/scripts/update_generation_config.sh +++ b/.github/scripts/update_generation_config.sh @@ -1,5 +1,5 @@ #!/bin/bash -set -e +set -ex # This script should be run at the root of the repository. # This script is used to update googleapis_commitish, gapic_generator_version, # and libraries_bom_version in generation configuration at the time of running @@ -15,8 +15,10 @@ set -e function get_latest_released_version() { local group_id=$1 local artifact_id=$2 - json_content=$(curl -s "https://search.maven.org/solrsearch/select?q=g:${group_id}+AND+a:${artifact_id}&core=gav&rows=500&wt=json") - latest=$(jq -r '.response.docs[] | select(.v | test("^[0-9]+(\\.[0-9]+)*$")) | .v' <<< "${json_content}" | sort -V | tail -n 1) + group_id_url_path="$(sed 's|\.|/|g' <<< "${group_id}")" + url="https://repo1.maven.org/maven2/${group_id_url_path}/${artifact_id}/maven-metadata.xml" + xml_content=$(curl -s --fail "${url}") + latest=$(xmllint --xpath 'metadata/versioning/latest/text()' - <<< "${xml_content}") if [[ -z "${latest}" ]]; then echo "The latest version of ${group_id}:${artifact_id} is empty." echo "The returned json from maven.org is invalid: ${json_content}" From 1ac0ba41947e638afd3926d8fbe0ae64fd9b7740 Mon Sep 17 00:00:00 2001 From: Diego Marquez Date: Thu, 24 Jul 2025 14:05:23 -0400 Subject: [PATCH 13/15] build: include update config yaml template (#3207) alternative to https://github.com/googleapis/java-storage/pull/3206 --- .github/workflows/update_generation_config.yaml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/update_generation_config.yaml b/.github/workflows/update_generation_config.yaml index cd2d5fd5a..7b14069ce 100644 --- a/.github/workflows/update_generation_config.yaml +++ b/.github/workflows/update_generation_config.yaml @@ -18,7 +18,6 @@ on: schedule: - cron: '0 2 * * *' workflow_dispatch: - jobs: update-generation-config: runs-on: ubuntu-24.04 @@ -30,6 +29,9 @@ jobs: with: fetch-depth: 0 token: ${{ secrets.CLOUD_JAVA_BOT_TOKEN }} + - name: Install Dependencies + shell: bash + run: sudo apt-get update && sudo apt-get install -y libxml2-utils - name: Update params in generation config to latest shell: bash run: | @@ -40,5 +42,4 @@ jobs: --base_branch "${base_branch}" \ --repo ${{ github.repository }} env: - GH_TOKEN: ${{ secrets.CLOUD_JAVA_BOT_TOKEN }} - + GH_TOKEN: ${{ secrets.CLOUD_JAVA_BOT_TOKEN }} \ No newline at end of file From bd1f199cf57c2b8039c303586d5beac64aeca0ba Mon Sep 17 00:00:00 2001 From: cloud-java-bot <122572305+cloud-java-bot@users.noreply.github.com> Date: Thu, 24 Jul 2025 15:20:26 -0400 Subject: [PATCH 14/15] chore: Update generation configuration at Thu Jul 24 18:07:08 UTC 2025 (#3198) * chore: Update generation configuration at Sat Jul 19 02:33:14 UTC 2025 * chore: Update generation configuration at Tue Jul 22 02:37:15 UTC 2025 * chore: generate libraries at Tue Jul 22 02:37:45 UTC 2025 * chore: Update generation configuration at Wed Jul 23 02:38:05 UTC 2025 * chore: Update generation configuration at Thu Jul 24 02:37:39 UTC 2025 * chore: Update generation configuration at Thu Jul 24 17:57:25 UTC 2025 * chore: generate libraries at Thu Jul 24 17:57:53 UTC 2025 * chore: generate libraries at Thu Jul 24 18:07:39 UTC 2025 --- .github/scripts/update_generation_config.sh | 2 +- .github/workflows/hermetic_library_generation.yaml | 2 +- .github/workflows/update_generation_config.yaml | 4 +++- .kokoro/presubmit/graalvm-native-a.cfg | 2 +- .kokoro/presubmit/graalvm-native-b.cfg | 2 +- .kokoro/presubmit/graalvm-native-c.cfg | 2 +- README.md | 8 ++++---- generation_config.yaml | 6 +++--- 8 files changed, 15 insertions(+), 13 deletions(-) diff --git a/.github/scripts/update_generation_config.sh b/.github/scripts/update_generation_config.sh index 92efcf881..3b890a76b 100644 --- a/.github/scripts/update_generation_config.sh +++ b/.github/scripts/update_generation_config.sh @@ -1,5 +1,5 @@ #!/bin/bash -set -ex +set -e # This script should be run at the root of the repository. # This script is used to update googleapis_commitish, gapic_generator_version, # and libraries_bom_version in generation configuration at the time of running diff --git a/.github/workflows/hermetic_library_generation.yaml b/.github/workflows/hermetic_library_generation.yaml index 4ce1c236a..876d040f3 100644 --- a/.github/workflows/hermetic_library_generation.yaml +++ b/.github/workflows/hermetic_library_generation.yaml @@ -43,7 +43,7 @@ jobs: with: fetch-depth: 0 token: ${{ secrets.CLOUD_JAVA_BOT_TOKEN }} - - uses: googleapis/sdk-platform-java/.github/scripts@v2.60.1 + - uses: googleapis/sdk-platform-java/.github/scripts@v2.60.2 if: env.SHOULD_RUN == 'true' with: base_ref: ${{ github.base_ref }} diff --git a/.github/workflows/update_generation_config.yaml b/.github/workflows/update_generation_config.yaml index 7b14069ce..a7e14bb48 100644 --- a/.github/workflows/update_generation_config.yaml +++ b/.github/workflows/update_generation_config.yaml @@ -18,6 +18,7 @@ on: schedule: - cron: '0 2 * * *' workflow_dispatch: + jobs: update-generation-config: runs-on: ubuntu-24.04 @@ -42,4 +43,5 @@ jobs: --base_branch "${base_branch}" \ --repo ${{ github.repository }} env: - GH_TOKEN: ${{ secrets.CLOUD_JAVA_BOT_TOKEN }} \ No newline at end of file + GH_TOKEN: ${{ secrets.CLOUD_JAVA_BOT_TOKEN }} + diff --git a/.kokoro/presubmit/graalvm-native-a.cfg b/.kokoro/presubmit/graalvm-native-a.cfg index 5cc939cf9..96b4fed86 100644 --- a/.kokoro/presubmit/graalvm-native-a.cfg +++ b/.kokoro/presubmit/graalvm-native-a.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.49.0" # {x-version-update:google-cloud-shared-dependencies:current} + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.50.2" # {x-version-update:google-cloud-shared-dependencies:current} } env_vars: { diff --git a/.kokoro/presubmit/graalvm-native-b.cfg b/.kokoro/presubmit/graalvm-native-b.cfg index fd0015918..76f048331 100644 --- a/.kokoro/presubmit/graalvm-native-b.cfg +++ b/.kokoro/presubmit/graalvm-native-b.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.49.0" # {x-version-update:google-cloud-shared-dependencies:current} + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.50.2" # {x-version-update:google-cloud-shared-dependencies:current} } env_vars: { diff --git a/.kokoro/presubmit/graalvm-native-c.cfg b/.kokoro/presubmit/graalvm-native-c.cfg index 424494b02..277aa2338 100644 --- a/.kokoro/presubmit/graalvm-native-c.cfg +++ b/.kokoro/presubmit/graalvm-native-c.cfg @@ -3,7 +3,7 @@ # Configure the docker image for kokoro-trampoline. env_vars: { key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.49.0" # {x-version-update:google-cloud-shared-dependencies:current} + value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.50.2" # {x-version-update:google-cloud-shared-dependencies:current} } env_vars: { diff --git a/README.md b/README.md index 60b2a6358..b75087fa2 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ If you are using Maven with [BOM][libraries-bom], add this to your pom.xml file: com.google.cloud libraries-bom - 26.63.0 + 26.64.0 pom import @@ -46,12 +46,12 @@ If you are using Maven without the BOM, add this to your dependencies: com.google.cloud google-cloud-storage - 2.53.2 + 2.53.3 com.google.cloud google-cloud-storage-control - 2.53.2 + 2.53.3 ``` @@ -59,7 +59,7 @@ If you are using Maven without the BOM, add this to your dependencies: If you are using Gradle 5.x or later, add this to your dependencies: ```Groovy -implementation platform('com.google.cloud:libraries-bom:26.61.0') +implementation platform('com.google.cloud:libraries-bom:26.64.0') implementation 'com.google.cloud:google-cloud-storage' ``` diff --git a/generation_config.yaml b/generation_config.yaml index 559faca1f..295ed2340 100644 --- a/generation_config.yaml +++ b/generation_config.yaml @@ -1,6 +1,6 @@ -gapic_generator_version: 2.59.0 -googleapis_commitish: 56f26a7d042d41ca5da9e7cdf16f427c7aee255d -libraries_bom_version: 26.61.0 +gapic_generator_version: 2.60.2 +googleapis_commitish: fb0d8ac09cd1c2d94e9da572f0ad4692c8781410 +libraries_bom_version: 26.64.0 libraries: - api_shortname: storage name_pretty: Cloud Storage From 4017026d17e96a49d78cb4d7b0cc0eeb07bb1002 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 28 Jul 2025 12:21:10 -0400 Subject: [PATCH 15/15] chore(main): release 2.54.0 (#3200) * chore(main): release 2.54.0 * chore: generate libraries at Thu Jul 24 19:21:13 UTC 2025 --------- Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> Co-authored-by: cloud-java-bot --- CHANGELOG.md | 23 +++++++++++++++++++ README.md | 6 ++--- gapic-google-cloud-storage-v2/pom.xml | 4 ++-- google-cloud-storage-bom/pom.xml | 16 ++++++------- google-cloud-storage-control/pom.xml | 4 ++-- google-cloud-storage/pom.xml | 4 ++-- grpc-google-cloud-storage-control-v2/pom.xml | 4 ++-- grpc-google-cloud-storage-v2/pom.xml | 4 ++-- pom.xml | 16 ++++++------- proto-google-cloud-storage-control-v2/pom.xml | 4 ++-- proto-google-cloud-storage-v2/pom.xml | 4 ++-- samples/snapshot/pom.xml | 6 ++--- storage-shared-benchmarking/pom.xml | 4 ++-- versions.txt | 14 +++++------ 14 files changed, 68 insertions(+), 45 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d5f0ec1a..740eacae7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,28 @@ # Changelog +## [2.54.0](https://github.com/googleapis/java-storage/compare/v2.53.3...v2.54.0) (2025-07-24) + + +### Features + +* Add BucketInfo.IpFilter ([#3177](https://github.com/googleapis/java-storage/issues/3177)) ([14a91ec](https://github.com/googleapis/java-storage/commit/14a91ec208067e6afc55923cffda5f69aa33d8b4)) +* Add default end-to-end checksumming for JournalingBlobWriteSessionConfig [#3180](https://github.com/googleapis/java-storage/issues/3180) ([fa0f6a0](https://github.com/googleapis/java-storage/commit/fa0f6a03380af78e239bd0079267649ba4138f38)) +* Add default end-to-end crc32c checksumming for several upload methods via grpc transport [#3176](https://github.com/googleapis/java-storage/issues/3176) ([fa0f6a0](https://github.com/googleapis/java-storage/commit/fa0f6a03380af78e239bd0079267649ba4138f38)) + + +### Bug Fixes + +* **deps:** Update the Java code generator (gapic-generator-java) to 2.60.2 ([bd1f199](https://github.com/googleapis/java-storage/commit/bd1f199cf57c2b8039c303586d5beac64aeca0ba)) +* Give user provided checksum precondition priority for Storage#create methods that accept byte[] [#3182](https://github.com/googleapis/java-storage/issues/3182) ([fa0f6a0](https://github.com/googleapis/java-storage/commit/fa0f6a03380af78e239bd0079267649ba4138f38)) +* Move crc32c computation before writing to disk for BufferToDiskThenUpload BlobWriteSession config [#3187](https://github.com/googleapis/java-storage/issues/3187) ([fa0f6a0](https://github.com/googleapis/java-storage/commit/fa0f6a03380af78e239bd0079267649ba4138f38)) + + +### Dependencies + +* Update dependency com.google.apis:google-api-services-storage to v1-rev20250718-2.0.0 ([#3203](https://github.com/googleapis/java-storage/issues/3203)) ([18978e4](https://github.com/googleapis/java-storage/commit/18978e4ec54790df2939490ef76fc19b9f72eb04)) +* Update dependency com.google.cloud:sdk-platform-java-config to v3.50.2 ([#3201](https://github.com/googleapis/java-storage/issues/3201)) ([782c3c4](https://github.com/googleapis/java-storage/commit/782c3c416583704a196b17f23e9c12c33659f67d)) +* Update googleapis/sdk-platform-java action to v2.60.1 ([#3196](https://github.com/googleapis/java-storage/issues/3196)) ([6ba56e5](https://github.com/googleapis/java-storage/commit/6ba56e5a4b86a75a9f48beccf79ff6d5fdd3e19f)) + ## [2.53.3](https://github.com/googleapis/java-storage/compare/v2.53.2...v2.53.3) (2025-07-09) diff --git a/README.md b/README.md index b75087fa2..121e15591 100644 --- a/README.md +++ b/README.md @@ -66,13 +66,13 @@ implementation 'com.google.cloud:google-cloud-storage' If you are using Gradle without BOM, add this to your dependencies: ```Groovy -implementation 'com.google.cloud:google-cloud-storage:2.53.3' +implementation 'com.google.cloud:google-cloud-storage:2.54.0' ``` If you are using SBT, add this to your dependencies: ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-storage" % "2.53.3" +libraryDependencies += "com.google.cloud" % "google-cloud-storage" % "2.54.0" ``` ## Authentication @@ -522,7 +522,7 @@ Java is a registered trademark of Oracle and/or its affiliates. [kokoro-badge-link-5]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-storage/java11.html [stability-image]: https://img.shields.io/badge/stability-stable-green [maven-version-image]: https://img.shields.io/maven-central/v/com.google.cloud/google-cloud-storage.svg -[maven-version-link]: https://central.sonatype.com/artifact/com.google.cloud/google-cloud-storage/2.53.3 +[maven-version-link]: https://central.sonatype.com/artifact/com.google.cloud/google-cloud-storage/2.54.0 [authentication]: https://github.com/googleapis/google-cloud-java#authentication [auth-scopes]: https://developers.google.com/identity/protocols/oauth2/scopes [predefined-iam-roles]: https://cloud.google.com/iam/docs/understanding-roles#predefined_roles diff --git a/gapic-google-cloud-storage-v2/pom.xml b/gapic-google-cloud-storage-v2/pom.xml index 3a601c38a..b531898a2 100644 --- a/gapic-google-cloud-storage-v2/pom.xml +++ b/gapic-google-cloud-storage-v2/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc gapic-google-cloud-storage-v2 - 2.53.4-SNAPSHOT + 2.54.0 gapic-google-cloud-storage-v2 GRPC library for gapic-google-cloud-storage-v2 com.google.cloud google-cloud-storage-parent - 2.53.4-SNAPSHOT + 2.54.0 diff --git a/google-cloud-storage-bom/pom.xml b/google-cloud-storage-bom/pom.xml index 0d51f2f59..d2e9a9f95 100644 --- a/google-cloud-storage-bom/pom.xml +++ b/google-cloud-storage-bom/pom.xml @@ -19,7 +19,7 @@ 4.0.0 com.google.cloud google-cloud-storage-bom - 2.53.4-SNAPSHOT + 2.54.0 pom com.google.cloud @@ -69,37 +69,37 @@ com.google.cloud google-cloud-storage - 2.53.4-SNAPSHOT + 2.54.0 com.google.api.grpc gapic-google-cloud-storage-v2 - 2.53.4-SNAPSHOT + 2.54.0 com.google.api.grpc grpc-google-cloud-storage-v2 - 2.53.4-SNAPSHOT + 2.54.0 com.google.api.grpc proto-google-cloud-storage-v2 - 2.53.4-SNAPSHOT + 2.54.0 com.google.cloud google-cloud-storage-control - 2.53.4-SNAPSHOT + 2.54.0 com.google.api.grpc grpc-google-cloud-storage-control-v2 - 2.53.4-SNAPSHOT + 2.54.0 com.google.api.grpc proto-google-cloud-storage-control-v2 - 2.53.4-SNAPSHOT + 2.54.0 diff --git a/google-cloud-storage-control/pom.xml b/google-cloud-storage-control/pom.xml index 416ffa54e..9a2320e07 100644 --- a/google-cloud-storage-control/pom.xml +++ b/google-cloud-storage-control/pom.xml @@ -5,13 +5,13 @@ 4.0.0 com.google.cloud google-cloud-storage-control - 2.53.4-SNAPSHOT + 2.54.0 google-cloud-storage-control GRPC library for google-cloud-storage-control com.google.cloud google-cloud-storage-parent - 2.53.4-SNAPSHOT + 2.54.0 diff --git a/google-cloud-storage/pom.xml b/google-cloud-storage/pom.xml index 13e44fd0b..245bb6ef0 100644 --- a/google-cloud-storage/pom.xml +++ b/google-cloud-storage/pom.xml @@ -2,7 +2,7 @@ 4.0.0 google-cloud-storage - 2.53.4-SNAPSHOT + 2.54.0 jar Google Cloud Storage https://github.com/googleapis/java-storage @@ -12,7 +12,7 @@ com.google.cloud google-cloud-storage-parent - 2.53.4-SNAPSHOT + 2.54.0 google-cloud-storage diff --git a/grpc-google-cloud-storage-control-v2/pom.xml b/grpc-google-cloud-storage-control-v2/pom.xml index 9e1627edd..5a3413ed0 100644 --- a/grpc-google-cloud-storage-control-v2/pom.xml +++ b/grpc-google-cloud-storage-control-v2/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc grpc-google-cloud-storage-control-v2 - 2.53.4-SNAPSHOT + 2.54.0 grpc-google-cloud-storage-control-v2 GRPC library for google-cloud-storage com.google.cloud google-cloud-storage-parent - 2.53.4-SNAPSHOT + 2.54.0 diff --git a/grpc-google-cloud-storage-v2/pom.xml b/grpc-google-cloud-storage-v2/pom.xml index a744a8f4a..49beaac99 100644 --- a/grpc-google-cloud-storage-v2/pom.xml +++ b/grpc-google-cloud-storage-v2/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc grpc-google-cloud-storage-v2 - 2.53.4-SNAPSHOT + 2.54.0 grpc-google-cloud-storage-v2 GRPC library for grpc-google-cloud-storage-v2 com.google.cloud google-cloud-storage-parent - 2.53.4-SNAPSHOT + 2.54.0 diff --git a/pom.xml b/pom.xml index 072cdcb17..02ce7678b 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.google.cloud google-cloud-storage-parent pom - 2.53.4-SNAPSHOT + 2.54.0 Storage Parent https://github.com/googleapis/java-storage @@ -82,7 +82,7 @@ com.google.cloud google-cloud-storage - 2.53.4-SNAPSHOT + 2.54.0 com.google.apis @@ -104,32 +104,32 @@ com.google.api.grpc proto-google-cloud-storage-v2 - 2.53.4-SNAPSHOT + 2.54.0 com.google.api.grpc grpc-google-cloud-storage-v2 - 2.53.4-SNAPSHOT + 2.54.0 com.google.api.grpc gapic-google-cloud-storage-v2 - 2.53.4-SNAPSHOT + 2.54.0 com.google.api.grpc grpc-google-cloud-storage-control-v2 - 2.53.4-SNAPSHOT + 2.54.0 com.google.api.grpc proto-google-cloud-storage-control-v2 - 2.53.4-SNAPSHOT + 2.54.0 com.google.cloud google-cloud-storage-control - 2.53.4-SNAPSHOT + 2.54.0 com.google.cloud diff --git a/proto-google-cloud-storage-control-v2/pom.xml b/proto-google-cloud-storage-control-v2/pom.xml index cca819358..164d36794 100644 --- a/proto-google-cloud-storage-control-v2/pom.xml +++ b/proto-google-cloud-storage-control-v2/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc proto-google-cloud-storage-control-v2 - 2.53.4-SNAPSHOT + 2.54.0 proto-google-cloud-storage-control-v2 Proto library for proto-google-cloud-storage-control-v2 com.google.cloud google-cloud-storage-parent - 2.53.4-SNAPSHOT + 2.54.0 diff --git a/proto-google-cloud-storage-v2/pom.xml b/proto-google-cloud-storage-v2/pom.xml index 6fe5a4cbf..02953fb8e 100644 --- a/proto-google-cloud-storage-v2/pom.xml +++ b/proto-google-cloud-storage-v2/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc proto-google-cloud-storage-v2 - 2.53.4-SNAPSHOT + 2.54.0 proto-google-cloud-storage-v2 PROTO library for proto-google-cloud-storage-v2 com.google.cloud google-cloud-storage-parent - 2.53.4-SNAPSHOT + 2.54.0 diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml index 40c96caaa..312b98666 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,12 +28,12 @@ com.google.cloud google-cloud-storage - 2.53.4-SNAPSHOT + 2.54.0 com.google.cloud google-cloud-storage-control - 2.53.4-SNAPSHOT + 2.54.0 compile @@ -70,7 +70,7 @@ com.google.cloud google-cloud-storage - 2.53.4-SNAPSHOT + 2.54.0 tests test diff --git a/storage-shared-benchmarking/pom.xml b/storage-shared-benchmarking/pom.xml index b55be369d..89e8fd00a 100644 --- a/storage-shared-benchmarking/pom.xml +++ b/storage-shared-benchmarking/pom.xml @@ -10,7 +10,7 @@ com.google.cloud google-cloud-storage-parent - 2.53.4-SNAPSHOT + 2.54.0 @@ -31,7 +31,7 @@ com.google.cloud google-cloud-storage - 2.53.4-SNAPSHOT + 2.54.0 tests diff --git a/versions.txt b/versions.txt index 70560e648..edce9b20a 100644 --- a/versions.txt +++ b/versions.txt @@ -1,10 +1,10 @@ # Format: # module:released-version:current-version -google-cloud-storage:2.53.3:2.53.4-SNAPSHOT -gapic-google-cloud-storage-v2:2.53.3:2.53.4-SNAPSHOT -grpc-google-cloud-storage-v2:2.53.3:2.53.4-SNAPSHOT -proto-google-cloud-storage-v2:2.53.3:2.53.4-SNAPSHOT -google-cloud-storage-control:2.53.3:2.53.4-SNAPSHOT -proto-google-cloud-storage-control-v2:2.53.3:2.53.4-SNAPSHOT -grpc-google-cloud-storage-control-v2:2.53.3:2.53.4-SNAPSHOT +google-cloud-storage:2.54.0:2.54.0 +gapic-google-cloud-storage-v2:2.54.0:2.54.0 +grpc-google-cloud-storage-v2:2.54.0:2.54.0 +proto-google-cloud-storage-v2:2.54.0:2.54.0 +google-cloud-storage-control:2.54.0:2.54.0 +proto-google-cloud-storage-control-v2:2.54.0:2.54.0 +grpc-google-cloud-storage-control-v2:2.54.0:2.54.0